bsptemplate/asspandvariant/template_variant/specific/lcd.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bsptemplate/asspandvariant/template_variant/specific/lcd.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,1009 @@
+// Copyright (c) 2004-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:
+// template\Template_Variant\Specific\lcd.cpp
+// Implementation of an LCD driver. 
+// This file is part of the Template Base port
+// N.B. This sample code assumes that the display supports setting the backlight on or off, 
+// as well as adjusting the contrast and the brightness.
+// 
+//
+
+
+
+#include <videodriver.h>
+#include "platform.h"
+#include <nkern.h>
+#include <kernel/kernel.h>
+#include <kernel/kern_priv.h>
+#include <kernel/kpower.h>
+#include <template_assp_priv.h>
+
+
+// TO DO: (mandatory)
+// If the display supports Contrast and/or Brightness control then supply the following defines:
+// This is only example code... you may need to modify it for your hardware
+const TInt KConfigInitialDisplayContrast	= 128;
+const TInt KConfigLcdMinDisplayContrast		= 1;
+const TInt KConfigLcdMaxDisplayContrast		= 255;
+const TInt KConfigInitialDisplayBrightness	= 128;
+const TInt KConfigLcdMinDisplayBrightness	= 1;
+const TInt KConfigLcdMaxDisplayBrightness	= 255;
+
+// TO DO: (mandatory)
+// define a macro to calculate the screen buffer size
+// This is only example code... you may need to modify it for your hardware
+// aBpp is the number of bits-per-pixel, aPpl is the number of pixels per line and 
+// aLpp number of lines per panel
+#define FRAME_BUFFER_SIZE(aBpp,aPpl,aLpp)	(aBpp*aPpl*aLpp)/8	
+																
+
+// TO DO: (mandatory)
+// define the physical screen dimensions
+// This is only example code... you need to modify it for your hardware
+const TUint	KConfigLcdWidth					= 640;		// 640 pixels per line
+const TUint	KConfigLcdHeight				= 480;		// 480 lines per panel
+
+// TO DO: (mandatory)
+// define the characteristics of the LCD display
+// This is only example code... you need to modify it for your hardware
+const TBool	KConfigLcdIsMono				= EFalse;
+const TBool	KConfigLcdPixelOrderLandscape	= ETrue;
+const TBool	KConfigLcdPixelOrderRGB			= ETrue;
+const TInt	KConfigLcdMaxDisplayColors		= 65536;
+
+
+// TO DO: (mandatory)
+// define the display dimensions in TWIPs
+// A TWIP is a 20th of a point.  A point is a 72nd of an inch
+// Therefore a TWIP is a 1440th of an inch
+// This is only example code... you need to modify it for your hardware
+const TInt	KConfigLcdWidthInTwips			= 9638;		// = 6.69 inches
+const TInt	KConfigLcdHeightInTwips			= 7370;		// = 5.11 inches
+
+// TO DO: (mandatory)
+// define the available display modes
+// This is only example code... you need to modify it for your hardware
+const TInt  KConfigLcdNumberOfDisplayModes	= 1;
+const TInt  KConfigLcdInitialDisplayMode	= 0;
+struct SLcdConfig
+	{
+	TInt iMode;
+	TInt iOffsetToFirstVideoBuffer;
+	TInt iLenghtOfVideoBufferInBytes;
+	TInt iOffsetBetweenLines;
+	TBool iIsPalettized;
+	TInt iBitsPerPixel;
+	};
+static const SLcdConfig Lcd_Mode_Config[KConfigLcdNumberOfDisplayModes]=
+	{
+		{
+		0,								// iMode
+		0,								// iOffsetToFirstVideoBuffer
+		FRAME_BUFFER_SIZE(8, KConfigLcdWidth, KConfigLcdHeight),	// iLenghtOfVideoBufferInBytes
+		KConfigLcdWidth,				// iOffsetBetweenLines
+		ETrue,							// iIsPalettized
+		8								// iBitsPerPixel
+		}
+	};	
+
+
+
+_LIT(KLitLcd,"LCD");
+
+//
+// TO DO: (optional)
+//
+// Add any private functions and data you require
+//
+NONSHARABLE_CLASS(DLcdPowerHandler) : public DPowerHandler
+	{
+public: 
+	DLcdPowerHandler();
+	~DLcdPowerHandler();
+	
+	// from DPowerHandler
+	void PowerDown(TPowerState);
+	void PowerUp();
+
+	void PowerUpDfc();
+	void PowerDownDfc();
+
+	TInt Create();
+	void DisplayOn();
+	void DisplayOff();
+	TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
+
+	void PowerUpLcd(TBool aSecure);
+	void PowerDownLcd();
+
+	void ScreenInfo(TScreenInfoV01& aInfo);
+	void WsSwitchOnScreen();
+	void WsSwitchOffScreen();
+	void HandleMsg();
+	void SwitchDisplay(TBool aSecure);
+
+	void SetBacklightState(TBool aState);
+	void BacklightOn();
+	void BacklightOff();
+	TInt SetContrast(TInt aContrast);
+	TInt SetBrightness(TInt aBrightness);
+
+private:
+	TInt SetPaletteEntry(TInt aEntry, TInt aColor);
+	TInt GetPaletteEntry(TInt aEntry, TInt* aColor);
+	TInt NumberOfPaletteEntries();
+	TInt GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure);
+	TInt GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo);
+	TInt SetDisplayMode(TInt aMode);
+	void SplashScreen();
+	TInt GetDisplayColors(TInt* aColors);
+
+private:
+	TBool iIsPalettized;
+	TBool iDisplayOn;				// to prevent a race condition with WServer trying to power up/down at the same time
+	DPlatChunkHw* iChunk;
+	DPlatChunkHw* iSecureChunk;
+	TBool iWsSwitchOnScreen;
+ 	TBool iSecureDisplay;
+	TDynamicDfcQue* iDfcQ;
+	TMessageQue iMsgQ;
+	TDfc iPowerUpDfc;
+	TDfc iPowerDownDfc;	
+	TVideoInfoV01 iVideoInfo;
+	TVideoInfoV01 iSecureVideoInfo;
+	NFastMutex iLock;				// protects against being preempted whilst manipulating iVideoInfo/iSecureVideoInfo
+	TPhysAddr ivRamPhys;
+	TPhysAddr iSecurevRamPhys;
+
+	TBool iBacklightOn;
+	TInt iContrast;
+	TInt iBrightness;
+	};
+
+
+/**
+HAL handler function
+
+@param	aPtr a pointer to an instance of DLcdPowerHandler
+@param	aFunction the function number
+@param	a1 an arbitrary parameter
+@param	a2 an arbitrary parameter
+*/
+LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
+	{
+	DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr;
+	return pH->HalFunction(aFunction,a1,a2);
+	}
+
+/**
+DFC for receiving messages from the power handler
+@param	aPtr a pointer to an instance of DLcdPowerHandler
+*/
+void rxMsg(TAny* aPtr)
+	{
+	DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr;
+	h.HandleMsg();
+	}
+
+/**
+DFC for powering up the device
+
+@param aPtr	aPtr a pointer to an instance of DLcdPowerHandler
+*/
+void power_up_dfc(TAny* aPtr)
+	{
+	((DLcdPowerHandler*)aPtr)->PowerUpDfc();
+	}
+
+/**
+DFC for powering down the device
+
+@param aPtr	aPtr a pointer to an instance of DLcdPowerHandler
+*/
+void power_down_dfc(TAny* aPtr)
+	{
+	((DLcdPowerHandler*)aPtr)->PowerDownDfc();
+	}
+
+
+/**
+Default constructor
+*/
+DLcdPowerHandler::DLcdPowerHandler() :
+		DPowerHandler(KLitLcd),
+		iMsgQ(rxMsg,this,NULL,1),
+		iPowerUpDfc(&power_up_dfc,this,6),
+		iPowerDownDfc(&power_down_dfc,this,7),
+		iBacklightOn(EFalse),
+		iContrast(KConfigInitialDisplayContrast),
+		iBrightness(KConfigInitialDisplayBrightness)
+	{
+	}
+
+DLcdPowerHandler::~DLcdPowerHandler()
+	{
+	if (iDfcQ)
+		iDfcQ->Destroy();
+	}
+
+/**
+Second-phase constructor 
+
+Called by factory function at ordinal 0
+*/
+TInt DLcdPowerHandler::Create()
+	{
+	const TInt KLCDDfcQPriority=27; // Equal to Kern::DfcQue0() priority
+	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KLCDDfcQPriority, _L("LCDPowerHandler"));
+	if (r != KErrNone)
+		{
+		return r;
+		}
+
+	// map the video RAM
+	TInt vSize = ((TemplateAssp*)Arch::TheAsic())->VideoRamSize();
+	ivRamPhys = TTemplate::VideoRamPhys();				// EXAMPLE ONLY: assume TTemplate interface class
+	r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
+	if (r != KErrNone)
+		return r;
+	
+	//create "secure" screen immediately after normal one
+	iSecurevRamPhys =  ivRamPhys + vSize;
+	TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
+	if (r2 != KErrNone)
+		return r2;
+
+	TUint* pV=(TUint*)iChunk->LinearAddress();
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::Create: VideoRamSize=%x, VideoRamPhys=%08x, VideoRamLin=%08x",vSize,ivRamPhys,pV));
+
+	// TO DO: (mandatory)
+	// initialise the palette for the initial display mode
+	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
+	//		 or could be offered as part of the hardware block that implemenst the lcd control
+	//
+
+	TUint* pV2=(TUint*)iSecureChunk->LinearAddress();
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::Create: Secure display VideoRamSize=%x, VideoRamPhys=%08x, VideoRamLin=%08x",vSize,iSecurevRamPhys,pV2));
+
+	// TO DO: (mandatory)
+	// initialise the secure screen's palette for the initial display mode
+	//
+	
+	// setup the video info structure, this'll be used to remember the video settings
+	iVideoInfo.iDisplayMode = KConfigLcdInitialDisplayMode;
+	iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetToFirstVideoBuffer;
+	iVideoInfo.iIsPalettized = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iIsPalettized;
+	iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetBetweenLines;
+	iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iBitsPerPixel;
+
+	iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth;
+	iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
+	iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
+	iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
+	iVideoInfo.iIsMono = KConfigLcdIsMono;
+	iVideoInfo.iVideoAddress=(TInt)pV;
+	iVideoInfo.iIsPixelOrderLandscape = KConfigLcdPixelOrderLandscape;
+	iVideoInfo.iIsPixelOrderRGB = KConfigLcdPixelOrderRGB;
+
+	iSecureVideoInfo = iVideoInfo;
+	iSecureVideoInfo.iVideoAddress = (TInt)pV2;
+
+	iDisplayOn = EFalse;
+	iSecureDisplay = EFalse;
+
+	// install the HAL function
+	r=Kern::AddHalEntry(EHalGroupDisplay, halFunction, this);
+	if (r!=KErrNone)
+		return r;
+
+	iPowerUpDfc.SetDfcQ(iDfcQ);
+	iPowerDownDfc.SetDfcQ(iDfcQ);
+	iMsgQ.SetDfcQ(iDfcQ);
+	iMsgQ.Receive();
+
+	// install the power handler
+	// power up the screen
+	Add();
+	DisplayOn();
+
+	SplashScreen();
+	
+	return KErrNone;
+	}
+
+/**
+Turn the display on
+May be called as a result of a power transition or from the HAL
+If called from HAL, then the display may be already be on (iDisplayOn == ETrue)
+*/
+void DLcdPowerHandler::DisplayOn()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("DisplayOn %d", iDisplayOn));
+	if (!iDisplayOn)				// may have been powered up already
+		{
+		iDisplayOn = ETrue;
+		PowerUpLcd(iSecureDisplay);
+		SetContrast(iContrast);
+		SetBrightness(iBrightness);
+		}
+	}
+
+/**
+Turn the display off
+May be called as a result of a power transition or from the HAL
+If called from Power Manager, then the display may be already be off (iDisplayOn == EFalse)
+if the platform is in silent running mode
+*/
+void DLcdPowerHandler::DisplayOff()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("DisplayOff %d", iDisplayOn));
+	if (iDisplayOn)
+		{
+		iDisplayOn = EFalse;
+		PowerDownLcd();
+		}
+	}
+
+/**
+Switch between secure and non-secure displays
+
+@param aSecure ETrue if switching to secure display
+*/
+void DLcdPowerHandler::SwitchDisplay(TBool aSecure)
+ 	{
+ 	if (aSecure)
+ 		{
+ 		if (!iSecureDisplay)
+ 			{
+ 			//switch to secure display
+ 			DisplayOff();
+ 			iSecureDisplay = ETrue;
+ 			DisplayOn();
+ 			}
+ 		}
+ 	else
+ 		{
+ 		if (iSecureDisplay)
+ 			{
+ 			//switch from secure display
+ 			DisplayOff();
+ 			iSecureDisplay = EFalse;
+ 			DisplayOn();
+ 			}
+ 		}
+ 	}
+
+/**
+DFC to power up the display
+*/
+void DLcdPowerHandler::PowerUpDfc()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("PowerUpDfc"));
+	DisplayOn();
+
+	PowerUpDone();				// must be called from a different thread than PowerUp()
+	}
+
+/**
+DFC to power down the display
+*/
+void DLcdPowerHandler::PowerDownDfc()
+	{
+	__KTRACE_OPT(KPOWER, Kern::Printf("PowerDownDfc"));
+	DisplayOff();
+	PowerDownDone();			// must be called from a different thread than PowerUp()
+	}
+
+/**
+Schedule the power-down DFC
+*/
+void DLcdPowerHandler::PowerDown(TPowerState)
+	{
+	iPowerDownDfc.Enque();		// schedules DFC to execute on this driver's thread
+	}
+
+/**
+Schedule the power-up DFC
+*/
+void DLcdPowerHandler::PowerUp()
+	{
+	iPowerUpDfc.Enque();		// schedules DFC to execute on this driver's thread
+	}
+
+/**
+Power up the display
+
+@param aSecure ETrue if powering up the secure display
+*/
+void DLcdPowerHandler::PowerUpLcd(TBool aSecure)
+    {
+
+	// TO DO: (mandatory)
+	// Power up the display and configure it ready for use
+	// Examples of things that may need initializing are:
+	// panel dimensions
+	// line & frame timings
+	// bits-per-pixel
+	// Configuring the DMA engine to map the video buffer in ivRamPhys or iSecurevRamPhys
+	// contrast, brightness, backlight
+	// power
+	// etc. etc.
+	//
+    }
+
+/**
+Power down the display and the backlight
+*/
+void DLcdPowerHandler::PowerDownLcd()
+    {
+	SetBacklightState(EFalse);
+
+	// TO DO: (mandatory)
+	// Power down the display & disable LCD DMA.
+	// May need to wait until the current frame has been output
+	//
+    }
+
+/**
+Set the Lcd contrast
+
+@param aValue the contrast setting
+*/
+TInt DLcdPowerHandler::SetContrast(TInt aValue)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetContrast(%d)", aValue));
+
+	if (aValue >= KConfigLcdMinDisplayContrast && aValue <= KConfigLcdMaxDisplayContrast)
+		{
+		iContrast=aValue;
+		
+		// TO DO: (mandatory)
+		// set the contrast
+		//
+		return KErrNone;
+		}
+
+	return KErrArgument;
+	}
+
+/**
+Set the Lcd brightness
+
+@param aValue the brightness setting
+*/
+TInt DLcdPowerHandler::SetBrightness(TInt aValue)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetBrightness(%d)", aValue));
+
+	if (aValue >= KConfigLcdMinDisplayBrightness && aValue <= KConfigLcdMaxDisplayBrightness)
+		{
+		iBrightness=aValue;
+
+		// TO DO: (mandatory)
+		// set the brightness
+		//
+		return KErrNone;
+		}
+	return KErrArgument;
+	}
+
+/**
+Turn the backlight on
+*/
+void DLcdPowerHandler::BacklightOn()
+    {
+	// TO DO: (mandatory)
+	// turn the backlight on
+	//
+    }
+
+/**
+Turn the backlight off
+*/
+void DLcdPowerHandler::BacklightOff()
+    {
+	// TO DO: (mandatory)
+	// turn the backlight off
+	//
+    }
+
+/**
+Set the state of the backlight
+
+@param aState ETrue if setting the backlight on
+*/
+void DLcdPowerHandler::SetBacklightState(TBool aState)
+	{
+	iBacklightOn=aState;
+	if (iBacklightOn)
+		BacklightOn();
+	else
+		BacklightOff();
+	}
+
+void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::ScreenInfo"));
+	anInfo.iWindowHandleValid=EFalse;
+	anInfo.iWindowHandle=NULL;
+	anInfo.iScreenAddressValid=ETrue;
+	anInfo.iScreenAddress=(TAny *)(iChunk->LinearAddress());
+	anInfo.iScreenSize.iWidth=KConfigLcdWidth;
+	anInfo.iScreenSize.iHeight=KConfigLcdHeight;
+	}
+
+/**
+Handle a message from the power handler
+*/
+void DLcdPowerHandler::HandleMsg(void)
+	{
+	
+	TMessageBase* msg = iMsgQ.iMessage;
+	if (msg == NULL)
+		return;
+
+	if (msg->iValue)
+		DisplayOn();
+	else
+		DisplayOff();
+	msg->Complete(KErrNone,ETrue);
+	}
+
+/**
+Send a message to the power-handler message queue to turn the display on
+*/
+void DLcdPowerHandler::WsSwitchOnScreen()
+	{
+	TThreadMessage& m=Kern::Message();
+	m.iValue = ETrue;
+	m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered up
+	}
+
+/**
+Send a message to the power-handler message queue to turn the display off
+*/
+void DLcdPowerHandler::WsSwitchOffScreen()
+	{
+	TThreadMessage& m=Kern::Message();
+	m.iValue = EFalse;
+	m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered down
+	}
+
+/**
+Return information about the current display mode
+
+@param	aInfo a structure supplied by the caller to be filled by this function.
+@param	aSecure ETrue if requesting information about the secure display
+@return	KErrNone if successful
+*/
+TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetCurrentDisplayModeInfo"));
+	NKern::FMWait(&iLock);
+	if (aSecure)
+ 		aInfo = iSecureVideoInfo;
+ 	else
+ 		aInfo = iVideoInfo;
+	NKern::FMSignal(&iLock);
+	return KErrNone;
+	}
+
+/**
+Return information about the specified display mode
+
+@param	aMode the display mode to query
+@param	aInfo a structure supplied by the caller to be filled by this function.
+@return	KErrNone if successful
+*/
+TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo)
+	{
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetSpecifiedDisplayModeInfo mode is %d",aMode));
+
+	if (aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
+		return KErrArgument;
+
+	NKern::FMWait(&iLock);
+	aInfo = iVideoInfo;
+	NKern::FMSignal(&iLock);
+
+	if (aMode != aInfo.iDisplayMode)
+		{
+		aInfo.iOffsetToFirstPixel=Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
+		aInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
+		aInfo.iOffsetBetweenLines=Lcd_Mode_Config[aMode].iOffsetBetweenLines;
+		aInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
+		}
+	return KErrNone;
+	}
+
+/**
+Set the display mode
+
+@param	aMode the display mode to set
+*/
+TInt DLcdPowerHandler::SetDisplayMode(TInt aMode)
+	{
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetDisplayMode = %d", aMode));
+
+	if (aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
+		return KErrArgument;
+
+	NKern::FMWait(&iLock);
+
+	// store the current mode
+	iVideoInfo.iDisplayMode = aMode;
+	iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
+	iVideoInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
+	iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[aMode].iOffsetBetweenLines;
+	iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
+
+	// store the current mode for secure screen
+	iSecureVideoInfo.iDisplayMode = aMode;
+	iSecureVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
+	iSecureVideoInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
+	iSecureVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[aMode].iOffsetBetweenLines;
+	iSecureVideoInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
+	
+	// TO DO: (mandatory)
+	// set bits per pixel on hardware
+	// May need to reconfigure DMA if video buffer size and location have changed
+	//
+	NKern::FMSignal(&iLock);
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetDisplayMode mode = %d, otfp = %d, palettized = %d, bpp = %d, obl = %d",
+		aMode, iVideoInfo.iOffsetToFirstPixel, iVideoInfo.iIsPalettized, iVideoInfo.iBitsPerPixel, iVideoInfo.iOffsetBetweenLines));
+
+	return KErrNone;
+	}
+
+/**
+Fill the video memory with an initial pattern or image
+This will be displayed on boot-up
+*/
+void DLcdPowerHandler::SplashScreen()
+	{
+	// TO DO: (optional)
+	// replace the example code below to display a different spash screen
+
+	// initialise the video ram to be a splash screen
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SplashScreen"));
+
+	TUint x,y;
+	TUint8 * p = (TUint8*)(iVideoInfo.iVideoAddress + iVideoInfo.iOffsetToFirstPixel);
+
+	//draw >< on screen
+	TUint rsh = KConfigLcdHeight;
+	TUint rsw = KConfigLcdWidth;
+	for (y = 0; y < rsh>>1; y++)
+		{
+		TUint8* q = p;
+		for (x = 0; x < rsw; x++)
+			*p++ = (x < y || (rsw-x<y)) ? 1 : 2;
+		p = q + iVideoInfo.iOffsetBetweenLines;
+		}
+	for (y = rsh>>1; y < rsh; y++)
+		{
+		TUint8* q = p;
+		for (x = 0; x < rsw; x++)
+			*p++ = ((x < rsh-y) || (rsw-x<rsh-y)) ? 1 : 2;
+		p = q + iVideoInfo.iOffsetBetweenLines;
+		}
+
+	p = (TUint8*)(iSecureVideoInfo.iVideoAddress + iSecureVideoInfo.iOffsetToFirstPixel);
+
+	//draw >< on secure screen
+	for (y = 0; y < rsh>>1; y++)
+		{
+		TUint8* q = p;
+		for (x = 0; x < rsw; x++)
+			*p++ = (x < y || (rsw-x<y)) ? 1 : 2;
+		p = q + iSecureVideoInfo.iOffsetBetweenLines;
+		}
+	for (y = rsh>>1; y < rsh; y++)
+		{
+		TUint8* q = p;
+		for (x = 0; x < rsw; x++)
+			*p++ = ((x < rsh-y) || (rsw-x<rsh-y)) ? 1 : 2;
+		p = q + iSecureVideoInfo.iOffsetBetweenLines;
+		}
+	}
+
+
+/**
+Get the size of the pallete
+
+@return	the number of pallete entries
+*/
+TInt DLcdPowerHandler::NumberOfPaletteEntries()		//only call when holding mutex
+	{
+	// TO DO: (mandatory)
+	// Calculate the number of Palette entries - this is normally 
+	// calculated from the bits per-pixel.
+	// This is only example code... you may need to modify it for your hardware
+	//
+	TInt num = iVideoInfo.iIsPalettized ? 1<<iVideoInfo.iBitsPerPixel : 0;
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("NumberOfPaletteEntries = %d", num));
+
+	return num;
+	}
+
+
+/** 
+Retrieve the palette entry at a particular offset
+
+@param	aEntry the palette index
+@param	aColor a caller-supplied pointer to a location where the returned RGB color is to be stored
+@return	KErrNone if successful
+		KErrNotSupported if the current vide mode does not support a palette
+		KErrArgument if aEntry is out of range
+*/
+TInt DLcdPowerHandler::GetPaletteEntry(TInt aEntry, TInt* aColor)
+	{
+	NKern::FMWait(&iLock);
+	if (!iVideoInfo.iIsPalettized)
+		{
+		NKern::FMSignal(&iLock);
+		return KErrNotSupported;
+		}
+
+	if ((aEntry < 0) || (aEntry >= NumberOfPaletteEntries()))
+		{
+		NKern::FMSignal(&iLock);
+		return KErrArgument;
+		}
+
+	// TO DO: (mandatory)
+	// read the RGB value of the palette entry into aColor
+	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
+	//		 or could be offered as part of the hardware block that implemenst the lcd control
+	//
+	NKern::FMSignal(&iLock);
+
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetPaletteEntry %d color 0x%x", aEntry, aColor));
+
+	return KErrNone;
+	}
+
+/** 
+Set the palette entry at a particular offset
+
+@param	aEntry the palette index
+@param	aColor the RGB color to store
+@return	KErrNone if successful
+		KErrNotSupported if the current vide mode does not support a palette
+		KErrArgument if aEntry is out of range
+*/
+TInt DLcdPowerHandler::SetPaletteEntry(TInt aEntry, TInt aColor)
+	{
+
+	NKern::FMWait(&iLock);
+	if (!iVideoInfo.iIsPalettized)
+		{
+		NKern::FMSignal(&iLock);
+		return KErrNotSupported;
+		}
+
+	if ((aEntry < 0) || (aEntry >= NumberOfPaletteEntries()))	//check entry in range
+		{
+		NKern::FMSignal(&iLock);
+		return KErrArgument;
+		}
+
+	// TO DO: (mandatory)
+	// update the palette entry for the secure and non-secure screen
+	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
+	//		 or could be offered as part of the hardware block that implemenst the lcd control
+	//
+	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetPaletteEntry %d to 0x%x", aEntry, aColor ));
+
+	return KErrNone;
+	}
+
+/**
+a HAL entry handling function for HAL group attribute EHalGroupDisplay
+
+@param	a1 an arbitrary argument
+@param	a2 an arbitrary argument
+@return	KErrNone if successful
+*/
+TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
+	{
+	__e32_memory_barrier(); // Ensure changes from other clients are picked up
+
+	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 EDisplayHalMaxDisplayContrast:
+			{
+			TInt mc=KConfigLcdMaxDisplayContrast;
+			kumemput32(a1,&mc,sizeof(mc));
+			break;
+			}
+		case EDisplayHalSetDisplayContrast:
+			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayContrast")))
+				return KErrPermissionDenied;
+			r=SetContrast(TInt(a1));
+			break;
+		
+		case EDisplayHalDisplayContrast:
+			kumemput32(a1,&iContrast,sizeof(iContrast));
+			break;
+
+		case EDisplayHalMaxDisplayBrightness:
+			{
+			TInt mc=KConfigLcdMaxDisplayBrightness;
+			kumemput32(a1,&mc,sizeof(mc));
+			break;
+			}
+		
+		case EDisplayHalSetDisplayBrightness:
+			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayBrightness")))
+				return KErrPermissionDenied;
+			r=SetBrightness(TInt(a1));
+			break;
+		
+		case EDisplayHalDisplayBrightness:
+			kumemput32(a1,&iBrightness,sizeof(iBrightness));
+			break;
+		
+		case EDisplayHalSetBacklightOn:
+			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetBacklightOn")))
+				return KErrPermissionDenied;
+			if (Kern::MachinePowerStatus()<ELow)
+				r=KErrBadPower;
+			else
+				SetBacklightState(TBool(a1));
+			break;
+		
+		case EDisplayHalBacklightOn:
+			kumemput32(a1,&iBacklightOn,sizeof(TInt));
+			break;
+
+		case EDisplayHalModeCount:
+			{
+			TInt ndm = KConfigLcdNumberOfDisplayModes;
+			kumemput32(a1, &ndm, sizeof(ndm));
+			break;
+			}
+		
+		case EDisplayHalSetMode:
+			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));
+			break;
+
+		case EDisplayHalSetPaletteEntry:
+			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry")))
+				return KErrPermissionDenied;
+			r = SetPaletteEntry((TInt)a1, (TInt)a2);
+			break;
+		
+		case EDisplayHalPaletteEntry:
+			{
+			TInt entry;
+			kumemget32(&entry, a1, sizeof(TInt));
+			TInt x;
+			r = GetPaletteEntry(entry, &x);
+			if (r == KErrNone)
+				kumemput32(a2, &x, sizeof(x));
+			break;
+			}
+		
+		case EDisplayHalSetState:
+			{
+			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 = KConfigLcdMaxDisplayColors;
+			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:
+			{
+			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure")))
+				return KErrPermissionDenied;
+			SwitchDisplay((TBool)a1);
+			}
+			break;
+
+		default:
+			r=KErrNotSupported;
+			break;
+		}
+
+	__e32_memory_barrier(); // Ensure any changes are propagated to other clients
+
+	return r;
+	}
+
+
+DECLARE_STANDARD_EXTENSION()
+	{
+	__KTRACE_OPT(KPOWER,Kern::Printf("Starting LCD power manager"));
+
+	// create LCD power handler
+	TInt r=KErrNoMemory;
+	DLcdPowerHandler* pH=new DLcdPowerHandler;
+	if (pH)
+		r=pH->Create();
+
+	__KTRACE_OPT(KPOWER,Kern::Printf("Returns %d",r));
+	return r;
+	}
+