bsptemplate/asspandvariant/template_variant/specific/lcd.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// 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;
	}