--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/baseport/syborg/svpframebuffer/svpframebuffer.cpp Wed Jan 27 14:42:12 2010 +0000
@@ -0,0 +1,1055 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Minimalistic frame buffer driver
+*
+*/
+#include <videodriver.h>
+#include "platform.h"
+#include <nkern.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+
+#include <syborg_priv.h>
+#include "svpframebuffer.h"
+
+DLcdPowerHandler * DLcdPowerHandler::pLcd = NULL;
+
+TPhysAddr Syborg::VideoRamPhys;
+TPhysAddr Syborg::VideoRamPhysSecure; // Secure display memory
+
+TPhysAddr TSyborg::VideoRamPhys()
+{
+ __KTRACE_OPT(KEXTENSION,Kern::Printf("TSyborg::VideoRamPhys: VideoRamPhys=0x%x", Syborg::VideoRamPhys));
+ return Syborg::VideoRamPhys;
+}
+
+TPhysAddr TSyborg::VideoRamPhysSecure()
+{
+ return Syborg::VideoRamPhysSecure;
+}
+
+LOCAL_C TInt DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
+{
+ DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr;
+ return pH->HalFunction(aFunction,a1,a2);
+}
+
+static void rxMsg(TAny* aPtr)
+{
+ DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr;
+ TMessageBase* pM = h.iMsgQ.iMessage;
+ if(pM)
+ h.HandleMsg(pM);
+}
+
+static void power_up_dfc(TAny* aPtr)
+{
+ ((DLcdPowerHandler*)aPtr)->PowerUpDfc();
+}
+
+void power_down_dfc(TAny* aPtr)
+{
+ ((DLcdPowerHandler*)aPtr)->PowerDownDfc();
+}
+
+void DLcdPowerHandler::DisplayOn()
+{
+ PowerUpLcd(iSecureDisplay);
+ iDisplayOn = ETrue;
+}
+
+void DLcdPowerHandler::DisplayOff()
+{
+ PowerDownLcd();
+ iDisplayOn = EFalse;
+}
+
+void DLcdPowerHandler::SwitchDisplay(TBool aSecure)
+ {
+ if(aSecure)
+ {
+ if(!iSecureDisplay)
+ {
+ DisplayOff();
+ iSecureDisplay = ETrue;
+ DisplayOn();
+ }
+ }
+ else
+ {
+ if(iSecureDisplay)
+ {
+ DisplayOff();
+ iSecureDisplay = EFalse;
+ DisplayOn();
+ }
+ }
+ }
+
+void DLcdPowerHandler::PowerUpDfc()
+{
+ DisplayOn();
+ PowerUpDone();
+}
+
+void DLcdPowerHandler::PowerDownDfc()
+{
+ DisplayOff();
+ PowerDownDone();
+}
+
+void DLcdPowerHandler::PowerDown(TPowerState)
+{
+ iPowerDownDfc.Enque();
+}
+
+void DLcdPowerHandler::PowerUp()
+{
+ iPowerUpDfc.Enque();
+}
+
+void DLcdPowerHandler::PowerUpLcd(TBool aSecure)
+{
+#if 1
+ WriteReg(iPortAddr, FB_ENABLED, 0);
+ WriteReg(iPortAddr, FB_BASE, aSecure ? iSecurevRamPhys : ivRamPhys);
+ WriteReg(iPortAddr, FB_WIDTH, iVideoInfo.iSizeInPixels.iWidth);
+ WriteReg(iPortAddr, FB_BLANK, 0);
+ WriteReg(iPortAddr, FB_BPP, 32);
+ WriteReg(iPortAddr, FB_COLOR_ORDER, 0);
+ WriteReg(iPortAddr, FB_BYTE_ORDER, 0);
+ WriteReg(iPortAddr, FB_PIXEL_ORDER, 0);
+ WriteReg(iPortAddr, FB_INT_MASK, 0);
+ WriteReg(iPortAddr, FB_ENABLED, 1);
+ WriteReg(iPortAddr, FB_HEIGHT, iVideoInfo.iSizeInPixels.iHeight);
+#endif
+}
+
+void DLcdPowerHandler::PowerDownLcd()
+{
+ WriteReg(iPortAddr, FB_BLANK, 1);
+}
+
+DLcdPowerHandler::DLcdPowerHandler()
+ : DPowerHandler(KLitLcd),
+ iMsgQ(rxMsg,this,NULL,1),
+ iPowerUpDfc(&power_up_dfc,this,6),
+ iPowerDownDfc(&power_down_dfc,this,7)
+{
+}
+
+void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo)
+{
+ anInfo.iWindowHandleValid = EFalse;
+ anInfo.iWindowHandle = NULL;
+ anInfo.iScreenAddressValid = ETrue;
+ anInfo.iScreenAddress = (TAny *)(iChunk->LinearAddress());
+ anInfo.iScreenSize.iWidth = iVideoInfo.iSizeInPixels.iWidth;
+ anInfo.iScreenSize.iHeight = iVideoInfo.iSizeInPixels.iHeight;
+}
+
+void DLcdPowerHandler::HandleMsg(TMessageBase* aMsg)
+{
+ if(aMsg->iValue)
+ DisplayOn();
+ else
+ DisplayOff();
+ aMsg->Complete(KErrNone,ETrue);
+}
+
+void DLcdPowerHandler::WsSwitchOnScreen()
+{
+ TThreadMessage& m = Kern::Message();
+ m.iValue = ETrue;
+ m.SendReceive(&iMsgQ);
+}
+
+void DLcdPowerHandler::WsSwitchOffScreen()
+{
+ TThreadMessage& m = Kern::Message();
+ m.iValue = EFalse;
+ m.SendReceive(&iMsgQ);
+}
+
+TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure)
+{
+ NKern::FMWait(&iLock);
+ if(aSecure)
+ aInfo = iSecureVideoInfo;
+ else
+ aInfo = iVideoInfo;
+ NKern::FMSignal(&iLock);
+ return KErrNone;
+}
+
+TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo)
+{
+ if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
+ return KErrArgument;
+
+ NKern::FMWait(&iLock);
+ aInfo = iVideoInfo;
+ NKern::FMSignal(&iLock);
+
+ if(aMode != aInfo.iDisplayMode)
+ {
+ aInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
+ aInfo.iIsPalettized = KConfigIsPalettized;
+ aInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
+ aInfo.iBitsPerPixel = KConfigBitsPerPixel;
+ }
+ return KErrNone;
+}
+
+TInt DLcdPowerHandler::AllocateFrameBuffer()
+{
+ // Allocate physical RAM for video
+ TInt vSize = TSyborg::VideoRamSize();
+
+ NKern::ThreadEnterCS();
+ TInt r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhys);
+ if (r != KErrNone)
+ {
+ NKern::ThreadLeaveCS();
+ Kern::Fault("AllocVideoRam",r);
+ }
+
+ // Map the video RAM
+ ivRamPhys = TSyborg::VideoRamPhys();
+
+ r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
+
+ NKern::ThreadLeaveCS();
+
+ if(r != KErrNone)
+ return r;
+
+ TUint* pV = (TUint*)iChunk->LinearAddress();
+
+ // Allocate physical RAM for secure display
+ NKern::ThreadEnterCS();
+ r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhysSecure);
+ if (r != KErrNone)
+ {
+ NKern::ThreadLeaveCS();
+ Kern::Fault("AllocVideoRam 2",r);
+ }
+ iSecurevRamPhys = ivRamPhys + vSize;
+ TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
+
+ NKern::ThreadLeaveCS();
+
+ if(r2 != KErrNone)
+ return r2;
+
+ TUint* pV2 = (TUint*)iSecureChunk->LinearAddress();
+
+ iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth;
+ iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
+ iVideoInfo.iDisplayMode = KConfigLcdDisplayMode;
+ iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
+ iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
+ iVideoInfo.iIsPalettized = KConfigIsPalettized;
+ iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel;
+ iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
+ iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
+ iVideoInfo.iIsMono = KConfigIsMono;
+ iVideoInfo.iVideoAddress = (TInt)pV;
+ iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape;
+ iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB;
+
+ iSecureVideoInfo = iVideoInfo;
+ iSecureVideoInfo.iVideoAddress = (TInt)pV2;
+
+ // Alloc Physical RAM for the Composition Buffers used by the GCE
+ iSize = 4*480*640;//FRAME_BUFFER_SIZE( iVideoInfo.iBitsPerPixel, iVideoInfo.iSizeInPixels.iWidth, iVideoInfo.iSizeInPixels.iHeight);
+ __GCE_DEBUG_PRINT2("DLcdPowerHandler.iSize = %d\n", iSize );
+ // double and round the page size
+ TUint round = 2*Kern::RoundToPageSize(iSize);
+
+ r=Epoc::AllocPhysicalRam(round , iCompositionPhysical);
+ if(r!=KErrNone)
+ {
+ return r;
+ }
+
+ return KErrNone;
+}
+
+
+TInt DLcdPowerHandler::SetDisplayMode(TInt aMode)
+{
+ if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
+ return KErrArgument;
+
+ // store the current mode
+ iVideoInfo.iDisplayMode = aMode;
+
+ // store the current mode for secure screen
+ iSecureVideoInfo.iDisplayMode = aMode;
+
+ return KErrNone;
+}
+
+TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
+{
+ TInt r=KErrNone;
+ switch(aFunction)
+ {
+ case EDisplayHalScreenInfo:
+ {
+ TPckgBuf<TScreenInfoV01> vPckg;
+ ScreenInfo(vPckg());
+ Kern::InfoCopy(*(TDes8*)a1,vPckg);
+ break;
+ }
+ case EDisplayHalWsRegisterSwitchOnScreenHandling:
+ {
+ iWsSwitchOnScreen=(TBool)a1;
+ break;
+ }
+ case EDisplayHalWsSwitchOnScreen:
+ {
+ WsSwitchOnScreen();
+ break;
+ }
+ case EDisplayHalModeCount:
+ {
+ TInt ndm = KConfigLcdNumberOfDisplayModes;
+ kumemput32(a1, &ndm, sizeof(ndm));
+ break;
+ }
+ case EDisplayHalSetMode:
+ {
+ __KTRACE_OPT(KEXTENSION,Kern::Printf("EDisplayHalSetMode"));
+ __SECURE_KERNEL(
+ if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode")))
+ return KErrPermissionDenied;
+ )
+ r = SetDisplayMode((TInt)a1);
+ break;
+ }
+ case EDisplayHalMode:
+ {
+ kumemput32(a1, &iVideoInfo.iDisplayMode, sizeof(iVideoInfo.iDisplayMode));
+ r = KErrNone;
+ break;
+ }
+ case EDisplayHalSetPaletteEntry:
+ {
+ __SECURE_KERNEL(
+ if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry")))
+ return KErrPermissionDenied;
+ )
+ r = KErrNotSupported;
+ break;
+ }
+ case EDisplayHalPaletteEntry:
+ {
+ TInt entry;
+ kumemget32(&entry, a1, sizeof(TInt));
+ r = KErrNotSupported;
+ break;
+ }
+ case EDisplayHalSetState:
+ {
+ __SECURE_KERNEL(
+ if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState")))
+ return KErrPermissionDenied;
+ )
+ if((TBool)a1)
+ WsSwitchOnScreen();
+ else
+ WsSwitchOffScreen();
+ break;
+ }
+ case EDisplayHalState:
+ {
+ kumemput32(a1, &iDisplayOn, sizeof(TBool));
+ break;
+ }
+ case EDisplayHalColors:
+ {
+ TInt mdc = 1<<24;
+ kumemput32(a1, &mdc, sizeof(mdc));
+ break;
+ }
+ case EDisplayHalCurrentModeInfo:
+ {
+ TPckgBuf<TVideoInfoV01> vPckg;
+ r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2);
+ if(KErrNone == r)
+ Kern::InfoCopy(*(TDes8*)a1,vPckg);
+ break;
+ }
+ case EDisplayHalSpecifiedModeInfo:
+ {
+ TPckgBuf<TVideoInfoV01> vPckg;
+ TInt mode;
+ kumemget32(&mode, a1, sizeof(mode));
+ r = GetSpecifiedDisplayModeInfo(mode, vPckg());
+ if(KErrNone == r)
+ Kern::InfoCopy(*(TDes8*)a2,vPckg);
+ break;
+ }
+ case EDisplayHalSecure:
+ {
+ kumemput32(a1, &iSecureDisplay, sizeof(TBool));
+ break;
+ }
+ case EDisplayHalSetSecure:
+ {
+ __SECURE_KERNEL(
+ if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure")))
+ return KErrPermissionDenied;
+ )
+ SwitchDisplay((TBool)a1);
+ break;
+ }
+ default:
+ {
+ r = KErrNotSupported;
+ break;
+ }
+ }
+ return r;
+}
+
+TInt DLcdPowerHandler::Create()
+{
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create") );
+ pLcd = this;
+
+ iPortAddr = KHwBaseClcd;
+
+ iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth;
+ iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
+ iVideoInfo.iDisplayMode = KConfigLcdDisplayMode;
+ iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
+ iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
+ iVideoInfo.iIsPalettized = KConfigIsPalettized;
+ iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel;
+ iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
+ iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
+ iVideoInfo.iIsMono = KConfigIsMono;
+ // !@! iVideoInfo.iVideoAddress = (TInt)pV;
+ iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape;
+ iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB;
+
+ iSecureVideoInfo = iVideoInfo;
+ // !@! iSecureVideoInfo.iVideoAddress = (TInt)pV2;
+
+ TInt r = AllocateFrameBuffer();
+ if(r == KErrNone)
+ {
+ r = Kern::AddHalEntry(EHalGroupDisplay,DoHalFunction,this);
+ }
+
+ if(r != KErrNone)
+ {
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create failed %d", r) );
+ return r;
+ }
+
+ iPowerUpDfc.SetDfcQ(iDfcQ);
+ iPowerDownDfc.SetDfcQ(iDfcQ);
+ iMsgQ.SetDfcQ(iDfcQ);
+ iMsgQ.Receive();
+
+ Add();
+ DisplayOn();
+
+ return KErrNone;
+}
+
+/**
+ * Register the call back function.
+ * Components interested in receiving notification of the Vsync interrupt should register a callback function.
+ */
+EXPORT_C TInt DLcdPowerHandler::RegisterCallback(TLcdUserCallBack* aCbPtr)
+{
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::RegisterCallBack %08x\n",aCbPtr->iCbFn) );
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock);
+
+ if(aCbPtr != NULL)
+ {
+ if ( pLcd->iAppCallBk[0] == NULL )
+ {
+ pLcd->iAppCallBk[0] = aCbPtr;
+ }
+ else
+ {
+ if((pLcd->iAppCallBk[1] == NULL) && (pLcd->iAppCallBk[0]->iCbFn != aCbPtr->iCbFn))
+ {
+ pLcd->iAppCallBk[1] = aCbPtr;
+ }
+ else
+ {
+ __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
+ return KErrInUse;
+ }
+ }
+
+ __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::RegisterCallBack ok %08x\n",aCbPtr->iCbFn) );
+ return KErrNone;
+ }
+ else
+ {
+ __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
+ __KTRACE_OPT(KEXTENSION, Kern::Printf("Error: The supplied listener's callback is NULL"));
+ return KErrArgument;
+ }
+}
+
+
+/**
+ *DeRegister the call back function
+ */
+EXPORT_C void DLcdPowerHandler::DeRegisterCallback(TLcdUserCallBack* aCbPtr)
+{
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn) );
+
+ TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock);
+ if(aCbPtr != NULL)
+ {
+ if( pLcd->iAppCallBk[0] != NULL)
+ {
+ if ( (pLcd->iAppCallBk[0]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[0]->iCbFn == aCbPtr->iCbFn) )
+ {
+ pLcd->iAppCallBk[0] = NULL;
+ }
+ }
+
+ if( pLcd->iAppCallBk[1] != NULL)
+ {
+ if ( (pLcd->iAppCallBk[1]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[1]->iCbFn == aCbPtr->iCbFn) )
+ {
+ pLcd->iAppCallBk[1] = NULL;
+ }
+ }
+ }
+ __SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
+ __KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn) );
+}
+
+/**
+ Constructor
+*/
+DDisplayPddSyborg::DDisplayPddSyborg():
+ iPendingBuffer(NULL),
+ iActiveBuffer(NULL),
+ iChunk(NULL),
+ iLcdCallback(NULL),
+ iVSyncDfc(&VSyncDfcFn, this, KVSyncDfcPriority)
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::DDisplayPddSyborg\n");
+
+ iPostFlag = EFalse;
+ }
+
+/**
+ Destructor
+*/
+DDisplayPddSyborg::~DDisplayPddSyborg()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::~DDisplayPddSyborg() \n");
+
+ if(iLcdCallback)
+ {
+ DLcdPowerHandler::pLcd->DeRegisterCallback(iLcdCallback) ;
+ delete iLcdCallback;
+ iLcdCallback = NULL;
+ }
+
+ //The DFC Queue is owned by DLcdPowerHandler so we shouldn't call Destroy() at this point.
+ if (iDfcQ)
+ {
+ iDfcQ=NULL;
+ }
+
+ DChunk* chunk = (DChunk*) __e32_atomic_swp_ord_ptr(&iChunk, 0);
+
+ if(chunk)
+ {
+ Kern::ChunkClose(chunk);
+ }
+
+ }
+
+/**
+ Set the Legacy Mode by setting the appropriate Frame control value.
+
+*/
+TInt DDisplayPddSyborg::SetLegacyMode()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetLegacyMode()\n");
+
+ return KErrNone;
+ }
+
+/**
+ Set the GCE mode by posting a composition buffer.
+
+*/
+TInt DDisplayPddSyborg::SetGceMode()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::SetGceMode()\n");
+
+ PostCompositionBuffer(&iLdd->iCompositionBuffer[0]);
+ return KErrNone;
+ }
+
+/**
+ @param aDegOfRot The requested rotation
+ @return KErrNone
+*/
+TInt DDisplayPddSyborg::SetRotation(TInt aDegOfRot)
+ {
+ return KErrNone;
+ }
+
+/**
+ Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
+ with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to
+ be posted next. Layer 3 is associated with user buffers.
+
+ @param aNode Pointer to the User buffer to post.
+*/
+TInt DDisplayPddSyborg::PostUserBuffer(TBufferNode* aNode)
+ {
+
+ __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostUserBuffer : aNode->iAddress = %08x\n", aNode->iAddress);
+
+ if(iPendingBuffer)
+ {
+ iPendingBuffer->iState = EBufferFree;
+ if (!(iPendingBuffer->iType == EBufferTypeUser) )
+ {
+ iPendingBuffer->iFree = ETrue;
+ }
+ }
+
+ aNode->iState = EBufferPending;
+ iPendingBuffer = aNode;
+ iPostFlag = ETrue;
+
+ // Activate the posted buffer
+ TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress );
+ WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress );
+ /* Queue a DFC to complete the request*/
+ iVSyncDfc.Enque();
+
+ return KErrNone;
+ }
+
+/**
+ Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
+ with V Sync so it will take affect in the next V Sync after that) and also set the buffer provided as the buffer to
+ be posted next. Layer 1 and 2 are associated with composition buffers 0 and 1 respectively.
+
+ @param aNode Pointer to the Composition buffer to post.
+*/
+TInt DDisplayPddSyborg::PostCompositionBuffer(TBufferNode* aNode)
+ {
+
+ __GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostCompositionBuffer : aNode->iAddress = %08x\n", aNode->iAddress);
+
+ if(iPendingBuffer)
+ {
+ iPendingBuffer->iState = EBufferFree;
+ if (iPendingBuffer->iType == EBufferTypeUser)
+ {
+ RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel);
+ }
+ else
+ {
+ iPendingBuffer->iFree = ETrue;
+ }
+ }
+ aNode->iState = EBufferPending;
+ aNode->iFree = EFalse;
+ iPendingBuffer = aNode;
+ iPostFlag = ETrue;
+
+ // Activate the posted buffer
+ TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress );
+ WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress );
+
+ /* Queue a DFC to complete the request*/
+ iVSyncDfc.Enque();
+
+ return KErrNone;
+ }
+
+/**
+ Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
+ with V Sync so it will take affect in the next V Sync after that) and also set the Legacy Buffer as the buffer to
+ be posted next.Layer 0 is associated with legacy buffer.
+
+ @param aNode Pointer to the Composition buffer to post.
+*/
+TInt DDisplayPddSyborg::PostLegacyBuffer()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::PostLegacyBuffer() \n");
+
+ if(iPendingBuffer)
+ {
+ iPendingBuffer->iState = EBufferFree;
+ if (iPendingBuffer->iType == EBufferTypeUser)
+ {
+
+ RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel);
+ }
+ else
+ {
+ iPendingBuffer->iFree = ETrue;
+ }
+ }
+
+
+ iLdd->iLegacyBuffer[0].iState = EBufferPending;
+ iLdd->iLegacyBuffer[0].iFree = EFalse;
+ iPendingBuffer = &iLdd->iLegacyBuffer[0];
+ iPostFlag = ETrue;
+
+ // Activate the posted buffer
+ WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, TSyborg::VideoRamPhys() );
+
+ /* Queue a DFC to complete the request*/
+ iVSyncDfc.Enque();
+
+ return KErrNone;
+ }
+
+/**
+ Handles device specific operations when a close message has been sent to the Logical Channel.
+
+*/
+TInt DDisplayPddSyborg::CloseMsg()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::CloseMsg()\n");
+
+ iPendingBuffer = NULL;
+ iActiveBuffer = NULL;
+
+ iVSyncDfc.Cancel();
+ return KErrNone;
+ }
+
+/**
+ Called by the LDD's DoCreate function to handle the device specific part of opening the channel.
+ (DoCreate is called by RDisplayChannel::Open)
+
+ @param aUnit The screen unit
+
+ @return KErrNone if successful; or one of the other system wide error codes.
+*/
+TInt DDisplayPddSyborg::CreateChannelSetup(TInt aUnit)
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddSyborg::CreateChannelSetup\n");
+
+ iScreenInfo = DLcdPowerHandler::pLcd->iVideoInfo;
+ iLdd->iUnit = aUnit;
+
+ iLdd->iDisplayInfo.iAvailableRotations = RDisplayChannel::ERotationNormal;
+ iLdd->iDisplayInfo.iNormal.iOffsetBetweenLines = iScreenInfo.iOffsetBetweenLines;
+ iLdd->iDisplayInfo.iNormal.iHeight = iScreenInfo.iSizeInPixels.iHeight;
+ iLdd->iDisplayInfo.iNormal.iWidth = iScreenInfo.iSizeInPixels.iWidth;
+ iLdd->iDisplayInfo.iNumCompositionBuffers = KDisplayCBMax;
+ iLdd->iDisplayInfo.iBitsPerPixel = iScreenInfo.iBitsPerPixel;
+ iLdd->iDisplayInfo.iRefreshRateHz = 60;
+
+
+ switch (iScreenInfo.iBitsPerPixel)
+ {
+ case 16:
+ iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_565;
+ break;
+ case 24:
+ iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_888;
+ break;
+ case 32:
+ iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatARGB_8888;
+ break;
+ default:
+ iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatUnknown;
+ break;
+ }
+
+ iLdd->iCurrentRotation = RDisplayChannel::ERotationNormal;
+
+ // Open shared chunk to the composition framebuffer
+
+ DChunk* chunk = 0;
+ TLinAddr chunkKernelAddr = 0;
+ TUint32 chunkMapAttr = 0;
+
+ // round to twice the page size
+ TUint round = 2*Kern::RoundToPageSize(DLcdPowerHandler::pLcd->iSize);
+
+ __GCE_DEBUG_PRINT2("DDisplayPddSyborg::CreateChannelSetup DLcdPowerHandler::pLcd->iSize = %d\n", DLcdPowerHandler::pLcd->iSize );
+
+ TChunkCreateInfo info;
+ info.iType = TChunkCreateInfo::ESharedKernelMultiple;
+ info.iMaxSize = round;
+ info.iMapAttr = EMapAttrFullyBlocking;
+ info.iOwnsMemory = EFalse;
+ info.iDestroyedDfc = 0;
+
+ TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr);
+
+ __GCE_DEBUG_PRINT2("CreateChannelSetup:ChunkCreate called for composition chunk. Set iChunkKernelAddr = %08x\n", chunkKernelAddr );
+
+ if( r == KErrNone)
+ {
+ // map our chunk
+ r = Kern::ChunkCommitPhysical(chunk, 0,round , DLcdPowerHandler::pLcd->iCompositionPhysical);
+ __GCE_DEBUG_PRINT2("Mapping chunk %d", r);
+ if(r != KErrNone)
+ {
+ Kern::ChunkClose(chunk);
+ }
+ }
+
+ if ( r!= KErrNone)
+ {
+ return r;
+ }
+
+ iChunk = chunk;
+
+ // init CB 0
+ iLdd->iCompositionBuffer[0].iType = EBufferTypeComposition;
+ iLdd->iCompositionBuffer[0].iBufferId = 0;
+ iLdd->iCompositionBuffer[0].iFree = ETrue;
+ iLdd->iCompositionBuffer[0].iState = EBufferFree;
+ iLdd->iCompositionBuffer[0].iAddress = chunkKernelAddr;
+ iLdd->iCompositionBuffer[0].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr);
+ iLdd->iCompositionBuffer[0].iChunk = chunk;
+ iLdd->iCompositionBuffer[0].iHandle = 0;
+ iLdd->iCompositionBuffer[0].iOffset = 0;
+ iLdd->iCompositionBuffer[0].iSize = DLcdPowerHandler::pLcd->iSize;
+ iLdd->iCompositionBuffer[0].iPendingRequest = 0;
+
+ // init CB 1
+ iLdd->iCompositionBuffer[1].iType = EBufferTypeComposition;
+ iLdd->iCompositionBuffer[1].iBufferId = 1;
+ iLdd->iCompositionBuffer[1].iFree = ETrue;
+ iLdd->iCompositionBuffer[1].iState = EBufferFree;
+ iLdd->iCompositionBuffer[1].iAddress = chunkKernelAddr + DLcdPowerHandler::pLcd->iSize;
+ iLdd->iCompositionBuffer[1].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr + DLcdPowerHandler::pLcd->iSize);
+ iLdd->iCompositionBuffer[1].iChunk = chunk;
+ iLdd->iCompositionBuffer[1].iHandle = 0;
+ iLdd->iCompositionBuffer[1].iOffset = DLcdPowerHandler::pLcd->iSize;
+ iLdd->iCompositionBuffer[1].iSize = DLcdPowerHandler::pLcd->iSize;
+ iLdd->iCompositionBuffer[1].iPendingRequest = 0;
+
+ iLdd->iCompositionBuffIdx = 0;
+ //Use the same DFC queue created by the DLcdPowerHandler so all hardware accesses are executed under the same DFC thread.
+ iDfcQ= DLcdPowerHandler::pLcd->iDfcQ;
+
+ // Set the Post DFC.
+ iVSyncDfc.SetDfcQ(iDfcQ);
+
+
+ return KErrNone;
+ }
+
+/**
+Detect whether a post operation is pending
+*/
+TBool DDisplayPddSyborg::PostPending()
+ {
+ return (iPendingBuffer != NULL);
+ }
+
+/**
+ Return the DFC queue to be used for this device.
+ */
+TDfcQue * DDisplayPddSyborg::DfcQ(TInt aUnit)
+ {
+ return iDfcQ;
+ }
+
+void DDisplayPddSyborg::VSyncDfcFn(TAny* aChannel)
+ {
+ DDisplayPddSyborg * channel =(DDisplayPddSyborg*)aChannel;
+
+ if (channel->iPostFlag)
+ {
+ channel->iPostFlag = EFalse;
+
+ if (channel->iActiveBuffer)
+ {
+ //When a User buffer is registered its iFree member becomes EFalse and Deregister sets it
+ //back to ETrue. Composition and Legacy buffers are not free when they are in the pending or
+ //active state.
+ if (channel->iActiveBuffer->iType == EBufferTypeUser)
+ {
+ channel->RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrNone);
+ }
+ else
+ {
+ channel->iActiveBuffer->iFree = ETrue;
+ }
+
+ channel->iActiveBuffer->iState = EBufferFree;
+
+
+ //If no buffer was available during a call to GetCompositionBuffer the active buffer has
+ //been returned as the next available one, so we must set the buffer to the proper state before we
+ //send the notification.
+ if(channel->iLdd->iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus)
+ {
+ channel->iActiveBuffer->iState = EBufferCompose;
+ channel->RequestComplete(RDisplayChannel::EReqGetCompositionBuffer, KErrNone);
+
+ }
+
+ channel->iActiveBuffer = NULL;
+ }
+
+ if (channel->iPendingBuffer)
+ {
+ __GCE_DEBUG_PRINT2("DDisplayPddSyborg::VSyncDfcFn moving pending buffer at address %08x to the active state\n", channel->iPendingBuffer->iAddress);
+ channel->iActiveBuffer = channel->iPendingBuffer;
+ channel->iActiveBuffer->iState = EBufferActive;
+ channel->iPendingBuffer = NULL;
+
+ channel->RequestComplete(RDisplayChannel::EReqWaitForPost, KErrNone);
+ }
+ }
+ }
+//*****************************************************************
+//DDisplayPddFactory
+//*****************************************************************/
+
+
+/**
+ Constructor
+*/
+DDisplayPddFactory::DDisplayPddFactory()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddFactory::DDisplayPddFactory()\n");
+
+ iVersion = TVersion(KDisplayChMajorVersionNumber,
+ KDisplayChMinorVersionNumber,
+ KDisplayChBuildVersionNumber);
+ }
+
+/**
+ PDD factory function. Creates a PDD object.
+
+ @param aChannel A pointer to an PDD channel object which will be initialised on return.
+
+ @return KErrNone if object successfully allocated, KErrNoMemory if not.
+*/
+TInt DDisplayPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
+ {
+ DDisplayPddSyborg *device= new DDisplayPddSyborg() ;
+ aChannel=device;
+ if (!device)
+ {
+ return KErrNoMemory;
+ }
+ return KErrNone;
+ }
+
+
+/**
+ Set the Pdd name and return error code
+*/
+TInt DDisplayPddFactory::Install()
+ {
+ __GCE_DEBUG_PRINT("DDisplayPddFactory::Install() \n");
+
+ TBuf<32> name(RDisplayChannel::Name());
+ _LIT(KPddExtension,".pdd");
+ name.Append(KPddExtension);
+ return SetName(&name);
+ }
+
+
+void DDisplayPddFactory::GetCaps(TDes8& /*aDes*/) const
+ {
+ //Not supported
+ }
+
+
+/**
+ Validate version and number of units.
+*/
+TInt DDisplayPddFactory::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer)
+ {
+ if (!Kern::QueryVersionSupported(iVersion,aVer))
+ {
+ return KErrNotSupported;
+ }
+
+ if (aUnit != 0)
+ {
+ return KErrNotSupported;
+ }
+
+ return KErrNone;
+ }
+
+DECLARE_EXTENSION_PDD()
+/**
+ "Standard PDD" entrypoint.Creates PDD factory when Kern::InstallPhysicalDevice is called
+
+ @return pointer to the PDD factory object.
+*/
+ {
+ __GCE_DEBUG_PRINT("DECLARE_EXTENSION_PDD()\n");
+ return new DDisplayPddFactory ;
+ }
+
+
+DECLARE_STANDARD_EXTENSION()
+{
+ TInt r = KErrNoMemory;
+ DLcdPowerHandler* pH=new DLcdPowerHandler;
+ if(pH)
+ {
+ r = pH->Create();
+ if ( r == KErrNone)
+ {
+ pH->iDfcQ = Kern::DfcQue0(); // use low priority DFC queue for this driver
+
+ DDisplayPddFactory * device = new DDisplayPddFactory;
+
+ if (device==NULL)
+ {
+ r=KErrNoMemory;
+ }
+ else
+ {
+ r=Kern::InstallPhysicalDevice(device);
+ }
+
+ #ifdef CPU_AFFINITY_ANY
+ NKern::ThreadSetCpuAffinity((NThread*) pH->iDfcQ->iThread, KCpuAffinityAny);
+ #endif
+
+ __KTRACE_OPT(KEXTENSION,Kern::Printf("Installing the display device from the kernel extension returned with error code %d",r));
+
+ }
+ }
+
+ return r;
+}