baseport/syborg/svpframebuffer/svpframebuffer.cpp
branchphonesim-integ
changeset 38 33dfab4ab0fc
child 46 b6935a90ca64
equal deleted inserted replaced
37:2925e6e5efd7 38:33dfab4ab0fc
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Minimalistic frame buffer driver
       
    15 *
       
    16 */
       
    17 #include <videodriver.h>
       
    18 #include "platform.h"
       
    19 #include <nkern.h>
       
    20 #include <kernel/kernel.h>
       
    21 #include <kernel/kern_priv.h>
       
    22 #include <kernel/kpower.h>
       
    23 
       
    24 #include <syborg_priv.h>
       
    25 #include "svpframebuffer.h"
       
    26 
       
    27 DLcdPowerHandler	*  DLcdPowerHandler::pLcd			= NULL;
       
    28 
       
    29 TPhysAddr Syborg::VideoRamPhys;
       
    30 TPhysAddr Syborg::VideoRamPhysSecure;		// Secure display memory
       
    31 
       
    32 TPhysAddr TSyborg::VideoRamPhys()
       
    33 {
       
    34   __KTRACE_OPT(KEXTENSION,Kern::Printf("TSyborg::VideoRamPhys: VideoRamPhys=0x%x", Syborg::VideoRamPhys));
       
    35   return Syborg::VideoRamPhys;
       
    36 }
       
    37 
       
    38 TPhysAddr TSyborg::VideoRamPhysSecure()
       
    39 {
       
    40   return Syborg::VideoRamPhysSecure;
       
    41 }
       
    42 
       
    43 LOCAL_C TInt DoHalFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
       
    44 {
       
    45   DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr;
       
    46   return pH->HalFunction(aFunction,a1,a2);
       
    47 }
       
    48 
       
    49 static void rxMsg(TAny* aPtr)
       
    50 {
       
    51   DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr;
       
    52   TMessageBase* pM = h.iMsgQ.iMessage;
       
    53   if(pM)
       
    54 	h.HandleMsg(pM);
       
    55 }
       
    56 
       
    57 static void power_up_dfc(TAny* aPtr)
       
    58 {
       
    59   ((DLcdPowerHandler*)aPtr)->PowerUpDfc();
       
    60 }
       
    61 
       
    62 void power_down_dfc(TAny* aPtr)
       
    63 {
       
    64   ((DLcdPowerHandler*)aPtr)->PowerDownDfc();
       
    65 }
       
    66 
       
    67 void DLcdPowerHandler::DisplayOn()
       
    68 { 
       
    69   PowerUpLcd(iSecureDisplay);
       
    70   iDisplayOn = ETrue;
       
    71 }
       
    72 
       
    73 void DLcdPowerHandler::DisplayOff()
       
    74 {
       
    75   PowerDownLcd();
       
    76   iDisplayOn = EFalse;
       
    77 }
       
    78 
       
    79 void DLcdPowerHandler::SwitchDisplay(TBool aSecure)
       
    80  {
       
    81    if(aSecure)
       
    82 	 {
       
    83 	   if(!iSecureDisplay)
       
    84 		 {
       
    85 		   DisplayOff();
       
    86 		   iSecureDisplay = ETrue;
       
    87 		   DisplayOn();
       
    88 		 }
       
    89 	 }
       
    90    else
       
    91 	 {
       
    92 	   if(iSecureDisplay)
       
    93 		 {
       
    94 		   DisplayOff();
       
    95 		   iSecureDisplay = EFalse;
       
    96 		   DisplayOn();
       
    97 		 }
       
    98 	 }
       
    99  }
       
   100 
       
   101 void DLcdPowerHandler::PowerUpDfc()
       
   102 {
       
   103   DisplayOn();
       
   104   PowerUpDone();
       
   105 }
       
   106 
       
   107 void DLcdPowerHandler::PowerDownDfc()
       
   108 {
       
   109   DisplayOff();
       
   110   PowerDownDone();
       
   111 }
       
   112 
       
   113 void DLcdPowerHandler::PowerDown(TPowerState)
       
   114 {
       
   115   iPowerDownDfc.Enque();
       
   116 }
       
   117 
       
   118 void DLcdPowerHandler::PowerUp()
       
   119 {
       
   120   iPowerUpDfc.Enque();
       
   121 }
       
   122 
       
   123 void DLcdPowerHandler::PowerUpLcd(TBool aSecure)
       
   124 {
       
   125 #if 1
       
   126   WriteReg(iPortAddr, FB_ENABLED, 0);
       
   127   WriteReg(iPortAddr, FB_BASE, aSecure ? iSecurevRamPhys : ivRamPhys);
       
   128   WriteReg(iPortAddr, FB_WIDTH, iVideoInfo.iSizeInPixels.iWidth);
       
   129   WriteReg(iPortAddr, FB_BLANK, 0);
       
   130   WriteReg(iPortAddr, FB_BPP, 32);
       
   131   WriteReg(iPortAddr, FB_COLOR_ORDER, 0);
       
   132   WriteReg(iPortAddr, FB_BYTE_ORDER, 0);
       
   133   WriteReg(iPortAddr, FB_PIXEL_ORDER, 0);
       
   134   WriteReg(iPortAddr, FB_INT_MASK, 0);
       
   135   WriteReg(iPortAddr, FB_ENABLED, 1);
       
   136   WriteReg(iPortAddr, FB_HEIGHT, iVideoInfo.iSizeInPixels.iHeight);
       
   137 #endif
       
   138 }
       
   139 
       
   140 void DLcdPowerHandler::PowerDownLcd()
       
   141 {
       
   142   WriteReg(iPortAddr, FB_BLANK, 1);
       
   143 }
       
   144 
       
   145 DLcdPowerHandler::DLcdPowerHandler()
       
   146 	:	DPowerHandler(KLitLcd),
       
   147 		iMsgQ(rxMsg,this,NULL,1),
       
   148 		iPowerUpDfc(&power_up_dfc,this,6),
       
   149 		iPowerDownDfc(&power_down_dfc,this,7)
       
   150 {
       
   151 }
       
   152 
       
   153 void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo)
       
   154 {
       
   155   anInfo.iWindowHandleValid = EFalse;
       
   156   anInfo.iWindowHandle = NULL;
       
   157   anInfo.iScreenAddressValid = ETrue;
       
   158   anInfo.iScreenAddress = (TAny *)(iChunk->LinearAddress());
       
   159   anInfo.iScreenSize.iWidth = iVideoInfo.iSizeInPixels.iWidth;
       
   160   anInfo.iScreenSize.iHeight = iVideoInfo.iSizeInPixels.iHeight;
       
   161 }
       
   162 
       
   163 void DLcdPowerHandler::HandleMsg(TMessageBase* aMsg)
       
   164 {
       
   165   if(aMsg->iValue)
       
   166 	DisplayOn();
       
   167   else
       
   168 	DisplayOff();
       
   169   aMsg->Complete(KErrNone,ETrue);
       
   170 }
       
   171 
       
   172 void DLcdPowerHandler::WsSwitchOnScreen()
       
   173 {
       
   174   TThreadMessage& m = Kern::Message();
       
   175   m.iValue = ETrue;
       
   176   m.SendReceive(&iMsgQ);
       
   177 }
       
   178 
       
   179 void DLcdPowerHandler::WsSwitchOffScreen()
       
   180 {
       
   181   TThreadMessage& m = Kern::Message();
       
   182   m.iValue = EFalse;
       
   183   m.SendReceive(&iMsgQ);
       
   184 }
       
   185 
       
   186 TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure)
       
   187 {
       
   188   NKern::FMWait(&iLock);
       
   189   if(aSecure)
       
   190 	aInfo = iSecureVideoInfo;
       
   191   else
       
   192 	aInfo = iVideoInfo;
       
   193   NKern::FMSignal(&iLock);
       
   194   return KErrNone;
       
   195 }
       
   196 
       
   197 TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo)
       
   198 {
       
   199   if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
       
   200 	return KErrArgument;
       
   201   
       
   202   NKern::FMWait(&iLock);
       
   203   aInfo = iVideoInfo;
       
   204   NKern::FMSignal(&iLock);
       
   205 
       
   206   if(aMode != aInfo.iDisplayMode)
       
   207 	{
       
   208 	  aInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
       
   209 	  aInfo.iIsPalettized       = KConfigIsPalettized;
       
   210 	  aInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
       
   211 	  aInfo.iBitsPerPixel       = KConfigBitsPerPixel;
       
   212 	}
       
   213   return KErrNone;
       
   214 }
       
   215 
       
   216 TInt DLcdPowerHandler::AllocateFrameBuffer()
       
   217 {
       
   218 	// Allocate physical RAM for video
       
   219 	TInt vSize = TSyborg::VideoRamSize();
       
   220 
       
   221 	NKern::ThreadEnterCS();
       
   222 	TInt r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhys);
       
   223 	if (r != KErrNone)
       
   224 	{
       
   225 	        NKern::ThreadLeaveCS();
       
   226 		Kern::Fault("AllocVideoRam",r);
       
   227 	}
       
   228 
       
   229 	// Map the video RAM
       
   230 	ivRamPhys = TSyborg::VideoRamPhys();
       
   231 
       
   232 	r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
       
   233 
       
   234 	NKern::ThreadLeaveCS();
       
   235 
       
   236 	if(r != KErrNone)
       
   237 	  return r;
       
   238 
       
   239 	TUint* pV = (TUint*)iChunk->LinearAddress();
       
   240 
       
   241 	// Allocate physical RAM for secure display
       
   242 	NKern::ThreadEnterCS();
       
   243 	r = Epoc::AllocPhysicalRam(vSize,Syborg::VideoRamPhysSecure);
       
   244 	if (r != KErrNone)
       
   245 	{
       
   246 	        NKern::ThreadLeaveCS();
       
   247 		Kern::Fault("AllocVideoRam 2",r);
       
   248 	}
       
   249 	iSecurevRamPhys = ivRamPhys + vSize;
       
   250 	TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
       
   251 
       
   252 	NKern::ThreadLeaveCS();
       
   253 
       
   254 	if(r2 != KErrNone)
       
   255 	  return r2;
       
   256 
       
   257 	TUint* pV2 = (TUint*)iSecureChunk->LinearAddress();
       
   258 
       
   259 	iVideoInfo.iSizeInPixels.iWidth  = KConfigLcdWidth;
       
   260 	iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
       
   261 	iVideoInfo.iDisplayMode = KConfigLcdDisplayMode;
       
   262 	iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
       
   263 	iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
       
   264 	iVideoInfo.iIsPalettized = KConfigIsPalettized;
       
   265 	iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel;
       
   266 	iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
       
   267 	iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
       
   268 	iVideoInfo.iIsMono = KConfigIsMono;
       
   269 	iVideoInfo.iVideoAddress = (TInt)pV;
       
   270 	iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape;
       
   271 	iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB;
       
   272 
       
   273 	iSecureVideoInfo = iVideoInfo;
       
   274 	iSecureVideoInfo.iVideoAddress = (TInt)pV2;
       
   275 
       
   276 	// Alloc Physical RAM for the Composition Buffers used by the GCE
       
   277 	iSize = 4*480*640;//FRAME_BUFFER_SIZE( iVideoInfo.iBitsPerPixel, iVideoInfo.iSizeInPixels.iWidth, iVideoInfo.iSizeInPixels.iHeight);
       
   278 	__GCE_DEBUG_PRINT2("DLcdPowerHandler.iSize  = %d\n", iSize );
       
   279 	// double and round the page size
       
   280 	TUint round = 2*Kern::RoundToPageSize(iSize);
       
   281 
       
   282 	r=Epoc::AllocPhysicalRam(round , iCompositionPhysical);
       
   283 	if(r!=KErrNone)
       
   284 		{
       
   285 		return r;
       
   286 		}
       
   287 	
       
   288 	return KErrNone;
       
   289 }
       
   290 
       
   291 
       
   292 TInt DLcdPowerHandler::SetDisplayMode(TInt aMode)
       
   293 {
       
   294   if(aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
       
   295 	return KErrArgument;
       
   296 
       
   297   // store the current mode
       
   298   iVideoInfo.iDisplayMode = aMode;
       
   299 
       
   300   // store the current mode for secure screen
       
   301   iSecureVideoInfo.iDisplayMode = aMode;
       
   302 
       
   303   return KErrNone;
       
   304 }
       
   305 
       
   306 TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
       
   307 {
       
   308   TInt r=KErrNone;
       
   309   switch(aFunction)
       
   310 	{
       
   311 	case EDisplayHalScreenInfo:
       
   312 	  {
       
   313 		TPckgBuf<TScreenInfoV01> vPckg;
       
   314 		ScreenInfo(vPckg());
       
   315 		Kern::InfoCopy(*(TDes8*)a1,vPckg);
       
   316 		break;
       
   317 	  }
       
   318 	case EDisplayHalWsRegisterSwitchOnScreenHandling:
       
   319 	  {
       
   320 		iWsSwitchOnScreen=(TBool)a1;
       
   321 		break;
       
   322 	  }
       
   323 	case EDisplayHalWsSwitchOnScreen:
       
   324 	  {
       
   325 		WsSwitchOnScreen();
       
   326 		break;
       
   327 	  }
       
   328 	case EDisplayHalModeCount:
       
   329 	  {
       
   330 		TInt ndm = KConfigLcdNumberOfDisplayModes;
       
   331 		kumemput32(a1, &ndm, sizeof(ndm));
       
   332 		break;
       
   333 	  }
       
   334 	case EDisplayHalSetMode:
       
   335 	  {
       
   336 		__KTRACE_OPT(KEXTENSION,Kern::Printf("EDisplayHalSetMode"));
       
   337 		__SECURE_KERNEL(
       
   338 						if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode")))
       
   339 						return KErrPermissionDenied;
       
   340 						)
       
   341 		  r = SetDisplayMode((TInt)a1);
       
   342 		break;
       
   343 	  }
       
   344 	case EDisplayHalMode:
       
   345 	  {
       
   346 		kumemput32(a1, &iVideoInfo.iDisplayMode, sizeof(iVideoInfo.iDisplayMode));
       
   347 		r = KErrNone;
       
   348 		break;
       
   349 	  }
       
   350 	case EDisplayHalSetPaletteEntry:
       
   351 	  {
       
   352 		__SECURE_KERNEL(
       
   353 						if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry")))
       
   354 						return KErrPermissionDenied;
       
   355 						)
       
   356 		  r = KErrNotSupported;
       
   357 		break;
       
   358 	  }
       
   359 	case EDisplayHalPaletteEntry:
       
   360 	  {
       
   361 		TInt entry;
       
   362 		kumemget32(&entry, a1, sizeof(TInt));
       
   363 		r = KErrNotSupported;
       
   364 		break;
       
   365 	  }
       
   366 	case EDisplayHalSetState:
       
   367 	  {
       
   368 		__SECURE_KERNEL(
       
   369 						if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState")))
       
   370 						return KErrPermissionDenied;
       
   371 						)
       
   372 		  if((TBool)a1)
       
   373 			WsSwitchOnScreen();
       
   374 		  else
       
   375 			WsSwitchOffScreen();
       
   376 		break;
       
   377 	  }
       
   378 	case EDisplayHalState:
       
   379 	  {
       
   380 		kumemput32(a1, &iDisplayOn, sizeof(TBool));
       
   381 		break;
       
   382 	  }
       
   383 	case EDisplayHalColors:
       
   384 	  {
       
   385 		TInt mdc = 1<<24;
       
   386 		kumemput32(a1, &mdc, sizeof(mdc));
       
   387 		break;
       
   388 	  }
       
   389 	case EDisplayHalCurrentModeInfo:
       
   390 	  {
       
   391 		TPckgBuf<TVideoInfoV01> vPckg;
       
   392 		r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2);
       
   393 		if(KErrNone == r)
       
   394 		  Kern::InfoCopy(*(TDes8*)a1,vPckg);
       
   395 		break;
       
   396 	  }
       
   397 	case EDisplayHalSpecifiedModeInfo:
       
   398 	  {
       
   399 		TPckgBuf<TVideoInfoV01> vPckg;
       
   400 		TInt mode;
       
   401 		kumemget32(&mode, a1, sizeof(mode));
       
   402 		r = GetSpecifiedDisplayModeInfo(mode, vPckg());
       
   403 		if(KErrNone == r)
       
   404 		  Kern::InfoCopy(*(TDes8*)a2,vPckg);
       
   405 		break;
       
   406 	  }	
       
   407 	case EDisplayHalSecure:
       
   408 	  {
       
   409 		kumemput32(a1, &iSecureDisplay, sizeof(TBool));
       
   410 		break;
       
   411 	  }
       
   412 	case EDisplayHalSetSecure:
       
   413 	  {
       
   414 		__SECURE_KERNEL(
       
   415 						if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure")))
       
   416 						return KErrPermissionDenied;
       
   417 						)
       
   418 		  SwitchDisplay((TBool)a1);
       
   419 		break;
       
   420 	  }
       
   421 	default:
       
   422 	  {
       
   423 		r = KErrNotSupported;
       
   424 		break;
       
   425 	  }			
       
   426 	}
       
   427   return r;
       
   428 }
       
   429 
       
   430 TInt DLcdPowerHandler::Create()
       
   431 {
       
   432 	__KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create") );
       
   433 	pLcd			= this;
       
   434 
       
   435 	iPortAddr = KHwBaseClcd;
       
   436 
       
   437 	iVideoInfo.iSizeInPixels.iWidth  = KConfigLcdWidth;
       
   438 	iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
       
   439 	iVideoInfo.iDisplayMode = KConfigLcdDisplayMode;
       
   440 	iVideoInfo.iOffsetToFirstPixel = KCOnfigOffsetToFirstPixel;
       
   441 	iVideoInfo.iOffsetBetweenLines = KCOnfigOffsetBetweenLines;
       
   442 	iVideoInfo.iIsPalettized = KConfigIsPalettized;
       
   443 	iVideoInfo.iBitsPerPixel = KConfigBitsPerPixel;
       
   444 	iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
       
   445 	iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
       
   446 	iVideoInfo.iIsMono = KConfigIsMono;
       
   447 	// !@!	iVideoInfo.iVideoAddress = (TInt)pV;
       
   448 	iVideoInfo.iIsPixelOrderLandscape = KConfigPixelOrderLandscape;
       
   449 	iVideoInfo.iIsPixelOrderRGB = KConfigPixelOrderRGB;
       
   450 
       
   451 	iSecureVideoInfo = iVideoInfo;
       
   452 	// !@! iSecureVideoInfo.iVideoAddress = (TInt)pV2;
       
   453 
       
   454 	TInt r = AllocateFrameBuffer();
       
   455 	if(r == KErrNone)
       
   456 		{
       
   457 		r = Kern::AddHalEntry(EHalGroupDisplay,DoHalFunction,this);
       
   458 		}
       
   459 	    
       
   460 	if(r != KErrNone)
       
   461 		{
       
   462 		__KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::Create failed %d", r) );
       
   463 		return r;
       
   464 		}
       
   465 
       
   466 	iPowerUpDfc.SetDfcQ(iDfcQ);
       
   467 	iPowerDownDfc.SetDfcQ(iDfcQ);
       
   468 	iMsgQ.SetDfcQ(iDfcQ);
       
   469 	iMsgQ.Receive();
       
   470 
       
   471 	Add();
       
   472 	DisplayOn();
       
   473 
       
   474 	return KErrNone;
       
   475 }
       
   476 
       
   477 /**
       
   478  * Register the call back function.
       
   479  * Components interested in receiving notification of the Vsync interrupt should register a callback function.
       
   480  */
       
   481 EXPORT_C TInt DLcdPowerHandler::RegisterCallback(TLcdUserCallBack* aCbPtr)
       
   482 {
       
   483 	__KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::RegisterCallBack %08x\n",aCbPtr->iCbFn) );
       
   484 
       
   485 	TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock);
       
   486 
       
   487 	if(aCbPtr != NULL)
       
   488 		{
       
   489 		if ( pLcd->iAppCallBk[0] == NULL  )
       
   490 			{
       
   491 			pLcd->iAppCallBk[0] = aCbPtr;
       
   492 			}
       
   493 		else
       
   494 			{
       
   495 			if((pLcd->iAppCallBk[1] == NULL) && (pLcd->iAppCallBk[0]->iCbFn != aCbPtr->iCbFn))
       
   496 				{
       
   497 				pLcd->iAppCallBk[1] = aCbPtr;
       
   498 				}
       
   499 			else
       
   500 				{
       
   501 				__SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
       
   502 				return KErrInUse;
       
   503 				}
       
   504 			}
       
   505 
       
   506 		__SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
       
   507 		__KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::RegisterCallBack ok %08x\n",aCbPtr->iCbFn) );
       
   508 		return KErrNone;
       
   509 		}
       
   510 	else
       
   511 		{
       
   512 		__SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
       
   513 		__KTRACE_OPT(KEXTENSION, Kern::Printf("Error: The supplied listener's callback is NULL"));
       
   514 		return KErrArgument;
       
   515 		}
       
   516 }
       
   517 
       
   518 
       
   519 /**
       
   520  *DeRegister the call back function
       
   521  */
       
   522 EXPORT_C void DLcdPowerHandler::DeRegisterCallback(TLcdUserCallBack* aCbPtr)
       
   523 {
       
   524 	__KTRACE_OPT(KEXTENSION ,Kern::Printf("DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn)  );
       
   525 
       
   526 	TInt irq=__SPIN_LOCK_IRQSAVE(callbackLock);
       
   527 	if(aCbPtr != NULL)
       
   528 		{
       
   529 	    if( pLcd->iAppCallBk[0] != NULL)
       
   530 			{
       
   531 			if ( (pLcd->iAppCallBk[0]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[0]->iCbFn == aCbPtr->iCbFn) )
       
   532 				{
       
   533 				pLcd->iAppCallBk[0] = NULL;
       
   534 				}
       
   535 			}
       
   536 
       
   537 		if( pLcd->iAppCallBk[1] != NULL)
       
   538 			{
       
   539 			if ( (pLcd->iAppCallBk[1]->iDataPtr == aCbPtr->iDataPtr) && (pLcd->iAppCallBk[1]->iCbFn == aCbPtr->iCbFn) )
       
   540 				{
       
   541 				pLcd->iAppCallBk[1] = NULL;
       
   542 				}
       
   543 			}
       
   544 		}
       
   545 	__SPIN_UNLOCK_IRQRESTORE(callbackLock,irq);
       
   546 	__KTRACE_OPT(KEXTENSION ,Kern::Printf("<DLcdPowerHandler::DeRegisterCallBack %08x\n ",aCbPtr->iCbFn)  );
       
   547 }
       
   548 
       
   549 /**
       
   550 	Constructor
       
   551 */
       
   552 DDisplayPddSyborg::DDisplayPddSyborg():
       
   553 	iPendingBuffer(NULL),
       
   554 	iActiveBuffer(NULL),
       
   555 	iChunk(NULL),
       
   556 	iLcdCallback(NULL),
       
   557 	iVSyncDfc(&VSyncDfcFn, this, KVSyncDfcPriority)
       
   558 	{
       
   559 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::DDisplayPddSyborg\n");
       
   560 
       
   561 	iPostFlag = EFalse;
       
   562 	}
       
   563 
       
   564 /**
       
   565 	Destructor
       
   566 */
       
   567 DDisplayPddSyborg::~DDisplayPddSyborg()
       
   568 	{
       
   569 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::~DDisplayPddSyborg()  \n");
       
   570 
       
   571 	if(iLcdCallback)
       
   572 		{
       
   573 		DLcdPowerHandler::pLcd->DeRegisterCallback(iLcdCallback) ;
       
   574 		delete iLcdCallback;
       
   575 		iLcdCallback = NULL;
       
   576 		}
       
   577 
       
   578 	//The DFC Queue is owned by DLcdPowerHandler so we shouldn't call Destroy() at this point.
       
   579 	if (iDfcQ)
       
   580 		{
       
   581 		iDfcQ=NULL;
       
   582 		}
       
   583 
       
   584 	DChunk* chunk = (DChunk*) __e32_atomic_swp_ord_ptr(&iChunk, 0);
       
   585 
       
   586 	if(chunk)
       
   587 		{
       
   588 		Kern::ChunkClose(chunk);
       
   589 		}
       
   590 
       
   591 	}
       
   592 
       
   593 /**
       
   594     Set the Legacy Mode by setting the appropriate Frame control value.
       
   595 
       
   596 */
       
   597 TInt DDisplayPddSyborg::SetLegacyMode()
       
   598 	{
       
   599 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::SetLegacyMode()\n");
       
   600 
       
   601     return KErrNone;
       
   602 	}
       
   603 
       
   604 /**
       
   605     Set the GCE mode by posting a composition buffer.
       
   606 
       
   607 */
       
   608 TInt DDisplayPddSyborg::SetGceMode()
       
   609 	{
       
   610 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::SetGceMode()\n");
       
   611 
       
   612     PostCompositionBuffer(&iLdd->iCompositionBuffer[0]);
       
   613     return KErrNone;
       
   614 	}
       
   615 
       
   616 /**
       
   617 	@param	aDegOfRot  The requested rotation
       
   618 	@return KErrNone
       
   619 */
       
   620 TInt DDisplayPddSyborg::SetRotation(TInt aDegOfRot)
       
   621 	{
       
   622 	return KErrNone;
       
   623 	}
       
   624 
       
   625 /**
       
   626     Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
       
   627     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
       
   628     be posted next. Layer 3 is associated with user buffers.
       
   629 
       
   630 	@param	aNode  Pointer to the User buffer to post.
       
   631 */
       
   632 TInt DDisplayPddSyborg::PostUserBuffer(TBufferNode* aNode)
       
   633 	{
       
   634 
       
   635 	__GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostUserBuffer :  aNode->iAddress = %08x\n", aNode->iAddress);
       
   636 
       
   637 	if(iPendingBuffer)
       
   638 		{
       
   639 		iPendingBuffer->iState = EBufferFree;
       
   640 		if (!(iPendingBuffer->iType == EBufferTypeUser) )
       
   641 			{
       
   642 			iPendingBuffer->iFree  = ETrue;
       
   643 			}
       
   644 		}
       
   645 
       
   646 	aNode->iState   = EBufferPending;
       
   647 	iPendingBuffer	= aNode;
       
   648 	iPostFlag		= ETrue;
       
   649 	
       
   650   	// Activate the posted buffer
       
   651 	TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress );
       
   652   	WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress );
       
   653 	/* Queue a DFC to complete the request*/
       
   654 	iVSyncDfc.Enque();
       
   655 
       
   656 	return KErrNone;
       
   657 	}
       
   658 
       
   659 /**
       
   660     Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
       
   661     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
       
   662     be posted next. Layer 1 and 2 are associated with composition buffers 0 and 1 respectively.
       
   663 
       
   664 	@param	aNode  Pointer to the Composition buffer to post.
       
   665 */
       
   666 TInt DDisplayPddSyborg::PostCompositionBuffer(TBufferNode* aNode)
       
   667 	{
       
   668 
       
   669 	__GCE_DEBUG_PRINT2("DDisplayPddSyborg::PostCompositionBuffer :  aNode->iAddress = %08x\n", aNode->iAddress);
       
   670 
       
   671 	if(iPendingBuffer)
       
   672 		{
       
   673 		iPendingBuffer->iState = EBufferFree;
       
   674 		if (iPendingBuffer->iType == EBufferTypeUser)
       
   675 			{
       
   676 			RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel);
       
   677 			}
       
   678 		else
       
   679 			{
       
   680 			iPendingBuffer->iFree  = ETrue;
       
   681 			}
       
   682 		}
       
   683 	aNode->iState	= EBufferPending;
       
   684 	aNode->iFree	= EFalse;
       
   685 	iPendingBuffer	= aNode;
       
   686 	iPostFlag		= ETrue;
       
   687 
       
   688   	// Activate the posted buffer
       
   689 	TUint32 physicalAddress = Epoc::LinearToPhysical( aNode->iAddress );
       
   690   	WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, physicalAddress );
       
   691 	
       
   692 	/* Queue a DFC to complete the request*/
       
   693 	iVSyncDfc.Enque();
       
   694 
       
   695 	return KErrNone;
       
   696 	}
       
   697 
       
   698 /**
       
   699     Remove any previous post operations, set the appropriate layer as the next layer to be displayed( This value is updated in synchronization
       
   700     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
       
   701     be posted next.Layer 0 is associated with legacy buffer.
       
   702 
       
   703 	@param	aNode  Pointer to the Composition buffer to post.
       
   704 */
       
   705 TInt DDisplayPddSyborg::PostLegacyBuffer()
       
   706 	{
       
   707 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::PostLegacyBuffer() \n");
       
   708 
       
   709 	if(iPendingBuffer)
       
   710 		{
       
   711 		iPendingBuffer->iState = EBufferFree;
       
   712 		if (iPendingBuffer->iType == EBufferTypeUser)
       
   713 			{
       
   714 
       
   715 			RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrCancel);
       
   716 			}
       
   717 		else
       
   718 			{
       
   719 			iPendingBuffer->iFree  = ETrue;
       
   720 			}
       
   721 		}
       
   722 
       
   723 
       
   724 	iLdd->iLegacyBuffer[0].iState		= EBufferPending;
       
   725 	iLdd->iLegacyBuffer[0].iFree		= EFalse;
       
   726 	iPendingBuffer						= &iLdd->iLegacyBuffer[0];
       
   727 	iPostFlag		= ETrue;
       
   728 
       
   729   	// Activate the posted buffer
       
   730   	WriteReg(DLcdPowerHandler::pLcd->iPortAddr, DLcdPowerHandler::FB_BASE, TSyborg::VideoRamPhys() );
       
   731 
       
   732 	/* Queue a DFC to complete the request*/
       
   733 	iVSyncDfc.Enque();
       
   734 
       
   735 	return KErrNone;
       
   736 	}
       
   737 
       
   738 /**
       
   739     Handles device specific operations when a close message has been sent to the Logical Channel.
       
   740 
       
   741 */
       
   742 TInt DDisplayPddSyborg::CloseMsg()
       
   743 	{
       
   744 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::CloseMsg()\n");
       
   745 
       
   746 	iPendingBuffer  = NULL;
       
   747 	iActiveBuffer	= NULL;
       
   748 
       
   749 	iVSyncDfc.Cancel();
       
   750     return KErrNone;
       
   751 	}
       
   752 
       
   753 /**
       
   754     Called by the LDD's DoCreate function to handle the device specific part of opening the channel.
       
   755     (DoCreate is called by RDisplayChannel::Open)
       
   756 
       
   757 	@param aUnit	The screen unit
       
   758 
       
   759     @return KErrNone if successful; or one of the other system wide error codes.
       
   760 */
       
   761 TInt DDisplayPddSyborg::CreateChannelSetup(TInt aUnit)
       
   762 	{
       
   763 	__GCE_DEBUG_PRINT("DDisplayPddSyborg::CreateChannelSetup\n");
       
   764 
       
   765 	iScreenInfo = DLcdPowerHandler::pLcd->iVideoInfo;
       
   766 	iLdd->iUnit = aUnit;
       
   767 
       
   768 	iLdd->iDisplayInfo.iAvailableRotations			= RDisplayChannel::ERotationNormal;
       
   769 	iLdd->iDisplayInfo.iNormal.iOffsetBetweenLines	= iScreenInfo.iOffsetBetweenLines;
       
   770 	iLdd->iDisplayInfo.iNormal.iHeight				= iScreenInfo.iSizeInPixels.iHeight;
       
   771 	iLdd->iDisplayInfo.iNormal.iWidth				= iScreenInfo.iSizeInPixels.iWidth;
       
   772 	iLdd->iDisplayInfo.iNumCompositionBuffers		= KDisplayCBMax;
       
   773 	iLdd->iDisplayInfo.iBitsPerPixel				= iScreenInfo.iBitsPerPixel;
       
   774     iLdd->iDisplayInfo.iRefreshRateHz = 60;
       
   775 
       
   776 
       
   777 	switch (iScreenInfo.iBitsPerPixel)
       
   778 		{
       
   779 		case 16:
       
   780 			iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_565;
       
   781 			break;
       
   782 		case 24:
       
   783 			iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatRGB_888;
       
   784 			break;
       
   785 		case 32:
       
   786 			iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatARGB_8888;
       
   787 			break;
       
   788 		default:
       
   789 			iLdd->iDisplayInfo.iPixelFormat = EUidPixelFormatUnknown;
       
   790 			break;
       
   791 		}
       
   792 
       
   793 	iLdd->iCurrentRotation = RDisplayChannel::ERotationNormal;
       
   794 
       
   795 	// Open shared chunk to the composition framebuffer
       
   796 
       
   797 	DChunk* chunk = 0;
       
   798 	TLinAddr chunkKernelAddr  = 0;
       
   799 	TUint32 chunkMapAttr = 0;
       
   800 
       
   801 	// round to twice the page size
       
   802 	TUint round  =  2*Kern::RoundToPageSize(DLcdPowerHandler::pLcd->iSize);
       
   803 
       
   804 	__GCE_DEBUG_PRINT2("DDisplayPddSyborg::CreateChannelSetup DLcdPowerHandler::pLcd->iSize  = %d\n", DLcdPowerHandler::pLcd->iSize );
       
   805 
       
   806 	TChunkCreateInfo info;
       
   807 	info.iType					 = TChunkCreateInfo::ESharedKernelMultiple;
       
   808 	info.iMaxSize				 = round;
       
   809 	info.iMapAttr				 = EMapAttrFullyBlocking;
       
   810 	info.iOwnsMemory			 = EFalse;
       
   811 	info.iDestroyedDfc			 = 0;
       
   812 
       
   813 	TInt r = Kern::ChunkCreate(info, chunk, chunkKernelAddr, chunkMapAttr);
       
   814 
       
   815 	__GCE_DEBUG_PRINT2("CreateChannelSetup:ChunkCreate called for composition chunk. Set iChunkKernelAddr  = %08x\n", chunkKernelAddr );
       
   816 
       
   817 	if( r == KErrNone)
       
   818 		{
       
   819 		// map our chunk
       
   820 		r = Kern::ChunkCommitPhysical(chunk, 0,round , DLcdPowerHandler::pLcd->iCompositionPhysical);
       
   821 		__GCE_DEBUG_PRINT2("Mapping chunk %d", r);
       
   822 		if(r != KErrNone)
       
   823 			{
       
   824 			Kern::ChunkClose(chunk);
       
   825 			}
       
   826 		}
       
   827 
       
   828 	if ( r!= KErrNone)
       
   829 		{
       
   830 		return r;
       
   831 		}
       
   832 
       
   833 	iChunk	= chunk;
       
   834 
       
   835 	// init CB 0
       
   836 	iLdd->iCompositionBuffer[0].iType			= EBufferTypeComposition;
       
   837 	iLdd->iCompositionBuffer[0].iBufferId		= 0;
       
   838 	iLdd->iCompositionBuffer[0].iFree			= ETrue;
       
   839 	iLdd->iCompositionBuffer[0].iState			= EBufferFree;
       
   840 	iLdd->iCompositionBuffer[0].iAddress		= chunkKernelAddr;
       
   841 	iLdd->iCompositionBuffer[0].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr);
       
   842 	iLdd->iCompositionBuffer[0].iChunk			= chunk;
       
   843 	iLdd->iCompositionBuffer[0].iHandle			= 0;
       
   844 	iLdd->iCompositionBuffer[0].iOffset			= 0;
       
   845 	iLdd->iCompositionBuffer[0].iSize			= DLcdPowerHandler::pLcd->iSize;
       
   846 	iLdd->iCompositionBuffer[0].iPendingRequest = 0;
       
   847 
       
   848 	// init CB 1
       
   849 	iLdd->iCompositionBuffer[1].iType			= EBufferTypeComposition;
       
   850 	iLdd->iCompositionBuffer[1].iBufferId		= 1;
       
   851 	iLdd->iCompositionBuffer[1].iFree			= ETrue;
       
   852 	iLdd->iCompositionBuffer[1].iState			= EBufferFree;
       
   853 	iLdd->iCompositionBuffer[1].iAddress		= chunkKernelAddr + DLcdPowerHandler::pLcd->iSize;
       
   854 	iLdd->iCompositionBuffer[1].iPhysicalAddress = Epoc::LinearToPhysical(chunkKernelAddr + DLcdPowerHandler::pLcd->iSize);
       
   855 	iLdd->iCompositionBuffer[1].iChunk			= chunk;
       
   856 	iLdd->iCompositionBuffer[1].iHandle			= 0;
       
   857 	iLdd->iCompositionBuffer[1].iOffset			= DLcdPowerHandler::pLcd->iSize;
       
   858 	iLdd->iCompositionBuffer[1].iSize			= DLcdPowerHandler::pLcd->iSize;
       
   859 	iLdd->iCompositionBuffer[1].iPendingRequest = 0;
       
   860 
       
   861 	iLdd->iCompositionBuffIdx					= 0;
       
   862 	//Use the same DFC queue created by the DLcdPowerHandler so all hardware accesses are executed under the same DFC thread.
       
   863 	iDfcQ= DLcdPowerHandler::pLcd->iDfcQ;
       
   864 
       
   865 	// Set the Post DFC.
       
   866 	iVSyncDfc.SetDfcQ(iDfcQ);
       
   867 
       
   868 
       
   869 	return KErrNone;
       
   870 	}
       
   871 
       
   872 /**
       
   873 Detect whether a post operation is pending
       
   874 */
       
   875 TBool DDisplayPddSyborg::PostPending()
       
   876 	{
       
   877 	return (iPendingBuffer != NULL);
       
   878 	}
       
   879 
       
   880 /**
       
   881 	Return the DFC queue to be used for this device.
       
   882  */
       
   883 TDfcQue * DDisplayPddSyborg::DfcQ(TInt aUnit)
       
   884 	{
       
   885 	return iDfcQ;
       
   886 	}
       
   887 
       
   888 void DDisplayPddSyborg::VSyncDfcFn(TAny* aChannel)
       
   889 	{
       
   890 	DDisplayPddSyborg * channel =(DDisplayPddSyborg*)aChannel;
       
   891 
       
   892 	if (channel->iPostFlag)
       
   893 		{
       
   894 		 channel->iPostFlag = EFalse;
       
   895 
       
   896 		if (channel->iActiveBuffer)
       
   897 			{
       
   898 			//When a User buffer is registered its iFree member becomes EFalse and Deregister sets it
       
   899 			//back to ETrue. Composition and Legacy buffers are not free when they are in the pending or
       
   900 			//active state.
       
   901 			if (channel->iActiveBuffer->iType == EBufferTypeUser)
       
   902 				{
       
   903 				channel->RequestComplete(RDisplayChannel::EReqPostUserBuffer, KErrNone);
       
   904 				}
       
   905 			else
       
   906 				{
       
   907 				channel->iActiveBuffer->iFree	= ETrue;
       
   908 				}
       
   909 
       
   910 			channel->iActiveBuffer->iState		= EBufferFree;
       
   911 
       
   912 
       
   913 			//If no buffer was available during a call to GetCompositionBuffer the active buffer has
       
   914 			//been returned as the next available one, so we must set the buffer to the proper state before we
       
   915 			//send the notification.
       
   916 			if(channel->iLdd->iPendingReq[RDisplayChannel::EReqGetCompositionBuffer].iStatus)
       
   917 				{
       
   918 				channel->iActiveBuffer->iState	= EBufferCompose;
       
   919 				channel->RequestComplete(RDisplayChannel::EReqGetCompositionBuffer, KErrNone);
       
   920 
       
   921 				}
       
   922 
       
   923 			channel->iActiveBuffer				= NULL;
       
   924 			}
       
   925 
       
   926 		if (channel->iPendingBuffer)
       
   927 			{
       
   928 			__GCE_DEBUG_PRINT2("DDisplayPddSyborg::VSyncDfcFn moving pending buffer at address %08x to the active state\n", channel->iPendingBuffer->iAddress);
       
   929 			channel->iActiveBuffer			= channel->iPendingBuffer;
       
   930 			channel->iActiveBuffer->iState	= EBufferActive;
       
   931 			channel->iPendingBuffer			= NULL;
       
   932 
       
   933 			channel->RequestComplete(RDisplayChannel::EReqWaitForPost,  KErrNone);
       
   934 			}
       
   935 		}
       
   936 	}
       
   937 //*****************************************************************
       
   938 //DDisplayPddFactory
       
   939 //*****************************************************************/
       
   940 
       
   941 
       
   942 /**
       
   943 	Constructor
       
   944 */
       
   945 DDisplayPddFactory::DDisplayPddFactory()
       
   946 	{
       
   947 	__GCE_DEBUG_PRINT("DDisplayPddFactory::DDisplayPddFactory()\n");
       
   948 
       
   949 	iVersion		= TVersion(KDisplayChMajorVersionNumber,
       
   950                       KDisplayChMinorVersionNumber,
       
   951                       KDisplayChBuildVersionNumber);
       
   952 	}
       
   953 
       
   954 /**
       
   955 	PDD factory function. Creates a PDD object.
       
   956 
       
   957 	@param  aChannel  A pointer to an PDD channel object which will be initialised on return.
       
   958 
       
   959 	@return KErrNone  if object successfully allocated, KErrNoMemory if not.
       
   960 */
       
   961 TInt DDisplayPddFactory::Create(DBase*& aChannel, TInt aUnit, const TDesC8* aInfo, const TVersion& aVer)
       
   962 	{
       
   963 	DDisplayPddSyborg *device= new DDisplayPddSyborg() ;
       
   964 	aChannel=device;
       
   965 	if (!device)
       
   966 		{
       
   967 		return KErrNoMemory;
       
   968 		}
       
   969 	return KErrNone;
       
   970 	}
       
   971 
       
   972 
       
   973 /**
       
   974     Set the Pdd name and return error code
       
   975 */
       
   976 TInt DDisplayPddFactory::Install()
       
   977 	{
       
   978 	__GCE_DEBUG_PRINT("DDisplayPddFactory::Install() \n");
       
   979 
       
   980 	TBuf<32> name(RDisplayChannel::Name());
       
   981 	_LIT(KPddExtension,".pdd");
       
   982 	name.Append(KPddExtension);
       
   983 	return SetName(&name);
       
   984 	}
       
   985 
       
   986 
       
   987 void DDisplayPddFactory::GetCaps(TDes8& /*aDes*/) const
       
   988 	{
       
   989 	//Not supported
       
   990 	}
       
   991 
       
   992 
       
   993 /**
       
   994     Validate version and number of units.
       
   995 */
       
   996 TInt DDisplayPddFactory::Validate(TInt aUnit, const TDesC8* /*anInfo*/, const TVersion& aVer)
       
   997 	{
       
   998 	if (!Kern::QueryVersionSupported(iVersion,aVer))
       
   999 		{
       
  1000 		return KErrNotSupported;
       
  1001 		}
       
  1002 
       
  1003 	if (aUnit != 0)
       
  1004 		{
       
  1005 		return KErrNotSupported;
       
  1006 		}
       
  1007 
       
  1008 	return KErrNone;
       
  1009 	}
       
  1010 
       
  1011 DECLARE_EXTENSION_PDD()
       
  1012 /**
       
  1013 	"Standard PDD" entrypoint.Creates PDD factory when Kern::InstallPhysicalDevice is called
       
  1014 
       
  1015 	@return pointer to the PDD factory object.
       
  1016 */
       
  1017 	{
       
  1018 	__GCE_DEBUG_PRINT("DECLARE_EXTENSION_PDD()\n");
       
  1019 	return new DDisplayPddFactory ;
       
  1020 	}
       
  1021 
       
  1022 
       
  1023 DECLARE_STANDARD_EXTENSION()
       
  1024 {
       
  1025   TInt r = KErrNoMemory;
       
  1026   DLcdPowerHandler* pH=new DLcdPowerHandler;
       
  1027   if(pH)
       
  1028 	{
       
  1029 	r = pH->Create();
       
  1030 	if ( r == KErrNone)
       
  1031 		{
       
  1032 		pH->iDfcQ = Kern::DfcQue0();	// use low priority DFC queue for this driver 
       
  1033 
       
  1034 		DDisplayPddFactory * device = new DDisplayPddFactory;
       
  1035 
       
  1036 		if (device==NULL)
       
  1037 			{
       
  1038 			r=KErrNoMemory;
       
  1039 			}
       
  1040 		else
       
  1041 			{
       
  1042 			r=Kern::InstallPhysicalDevice(device);
       
  1043 			}
       
  1044 
       
  1045 		#ifdef CPU_AFFINITY_ANY
       
  1046         NKern::ThreadSetCpuAffinity((NThread*) pH->iDfcQ->iThread, KCpuAffinityAny);
       
  1047 		#endif
       
  1048 
       
  1049 		__KTRACE_OPT(KEXTENSION,Kern::Printf("Installing the display device from the kernel extension returned with error code %d",r));
       
  1050 
       
  1051 		}
       
  1052 	}
       
  1053   
       
  1054   return r;
       
  1055 }