diff -r 000000000000 -r 6663340f3fc9 omap3530/beagle_drivers/lcd/lcd.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/omap3530/beagle_drivers/lcd/lcd.cpp Thu Oct 15 12:59:54 2009 +0100 @@ -0,0 +1,1241 @@ +// 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: +// omap3530/beagle_drivers/lcd/lcd.cpp +// Implementation of an LCD driver. +// This file is part of the Beagle 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define DSS_SYSCONFIG 0x48050010 +#define DISPC_SYSSTATUS 0x48050414 + +#define DISPC_SYSCONFIG 0x48050410 +#define DISPC_CONFIG 0x48050444 +#define DISPC_DEFAULT_COLOR0 0x4805044c +#define DISPC_TRANS_COLOR0 0x48050454 + +#define DISPC_TIMING_H 0x48050464 +#define DISPC_TIMING_V 0x48050468 +#define DISPC_POL_FREQ 0x4805046c +#define DISPC_DIVISOR 0x48050470 +#define DISPC_SIZE_LCD 0x4805047c + +#define DISPC_GFX_BA1 0x48050480 +#define DISPC_GFX_BA2 0x48050484 +#define DISPC_GFX_POSITION 0x48050488 +#define DISPC_GFX_SIZE 0x4805048c +#define DISPC_GFX_ATTRIBUTES 0x480504a0 + +#define DISPC_GFX_FIFO_THRESHOLD 0x480504a4 +#define DISPC_GFX_FIFO_SIZE_STATUS 0x480504a8 +#define DISPC_GFX_ROW_INC 0x480504ac +#define DISPC_GFX_PIXEL_INC 0x480504b0 +#define DISPC_GFX_WINDOW_SKIP 0x480504b4 +#define DISPC_GFX_TABLE_BA 0x480504b8 + +#define DISPC_CONTROL 0x48050440 + +#define GET_REGISTER(Reg) *( (TUint *) Omap3530HwBase::TVirtual::Value ) +#define SET_REGISTER(Reg,Val) *( (TUint *) Omap3530HwBase::TVirtual::Value ) = Val + +#define _MODE_1280x1024_ +//#define _MODE_1024x768_ +#ifdef _MODE_800x600_ +// ModeLine "800x600@60" 40.0 800 840 968 1056 600 601 605 628 +hsync +vsync +// Decoded by: http://www.tkk.fi/Misc/Electronics/faq/vga2rgb/calc.html +# define PIXEL_CLK 40000 +# define H_DISP 800 +# define H_FPORCH 40 +# define H_SYNC 128 +# define H_BPORCH 88 +# define H_SYNC_POL 1 +# define V_DISP 600 +# define V_FPORCH 1 +# define V_SYNC 4 +# define V_BPORCH 23 +# define V_SYNC_POL 1 +# define INTERLACE_ENABLE 0 +#endif +#ifdef _MODE_1024x768_ +// ModeLine "1024x768@60" 65.0 1024 1048 1184 1344 768 771 777 806 -hsync -vsync +// Decoded by: http://www.tkk.fi/Misc/Electronics/faq/vga2rgb/calc.html +# define PIXEL_CLK 65000 +# define H_DISP 1024 +# define H_FPORCH 24 +# define H_SYNC 136 +# define H_BPORCH 160 +# define H_SYNC_POL 0 +# define V_DISP 768 +# define V_FPORCH 3 +# define V_SYNC 6 +# define V_BPORCH 29 +# define V_SYNC_POL 0 +# define INTERLACE_ENABLE 0 +#endif +#ifdef _MODE_1280x1024_ +// ModeLine "1280x1024@60" 108.0 1280 1328 1440 1688 1024 1025 1028 1066 +hsync +vsync +// Decoded by: http://www.tkk.fi/Misc/Electronics/faq/vga2rgb/calc.html +# define PIXEL_CLK 108000 +# define H_DISP 1280 +# define H_FPORCH 48 +# define H_SYNC 112 +# define H_BPORCH 248 +# define H_SYNC_POL 1 +# define V_DISP 1024 +# define V_FPORCH 1 +# define V_SYNC 3 +# define V_BPORCH 38 +# define V_SYNC_POL 1 +# define INTERLACE_ENABLE 0 +#endif + + + +// 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 = 360;//640; // 640 pixels per line +const TUint KConfigLcdHeight = 640;//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; //24bit: 16777216; + + +// 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;//10800; // = 6.69 inches //15*1440; +const TInt KConfigLcdHeightInTwips = 7370;//11232;//5616; // = 5.11 inches //12*1440; + +// 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(16, KConfigLcdWidth, KConfigLcdHeight), // iLenghtOfVideoBufferInBytes + KConfigLcdWidth*2, // iOffsetBetweenLines + EFalse, // iIsPalettized + 16 // iBitsPerPixel + } + }; + + + +_LIT(KLitLcd,"LCD"); + +// +// TO DO: (optional) +// +// Add any private functions and data you require +// +NONSHARABLE_CLASS(DLcdPowerHandler) : public DPowerHandler + { +public: + 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; + TDfcQue* 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) + { + } + + +/** +Second-phase constructor + +Called by factory function at ordinal 0 +*/ +TInt DLcdPowerHandler::Create() + { + iDfcQ=Kern::DfcQue0(); // use low priority DFC queue for this driver + + // map the video RAM + + //TPhysAddr videoRamPhys; + TInt vSize = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iLenghtOfVideoBufferInBytes; //KConfigLcdWidth*KConfigLcdHeight*3; //VideoRamSize(); + TInt r = Epoc::AllocPhysicalRam( 2*vSize, ivRamPhys ); + if ( r!=KErrNone ) + { + Kern::Fault( "AllocVRam", r ); + } + + //TInt vSize = ((Omap3530BoardAssp*)Arch::TheAsic())->VideoRamSize(); + //ivRamPhys = TOmap3530Assp::VideoRamPhys(); // EXAMPLE ONLY: assume TOmap3530Assp 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(KBOOT, 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(KBOOT, 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) + { + + TUint32 l = 0x0; + + // Set up the Display Subsystem to control a DVI monitor + + // The following four lines need to be replaced by a call to the GPIO driver which should call the PowerClock driver +// PowerClock::GpioActive(0, PowerClock::E1s, PowerClock::ECpu10, PowerClock::EBus10); +// PowerClock::GpioAccess(0, PowerClock::EAuto); + Prcm::SetClockState( Prcm::EClkGpio1_F, Prcm::EClkOn ); + Prcm::SetClockState( Prcm::EClkGpio1_I, Prcm::EClkAuto ); + *( (TUint *) Omap3530HwBase::TVirtual<0x48310034>::Value ) = 0xfefffedf; //GPIO1 output enable p3336 + *( (TUint *) Omap3530HwBase::TVirtual<0x48310094>::Value ) = 0x01000120; //GPIO1 set data out p3336 +// const TUint KCM_CLKSEL_DSS = Omap3530HwBase::TVirtual<0x48004E40>::Value; +// Prcm::Set(KCM_CLKSEL_DSS, 0xffffffffu, 0x00001006); + + Prcm::SetDivider( Prcm::EClkDss1_F, 2 ); + Prcm::SetDivider( Prcm::EClkTv_F, 1 ); + + + SET_REGISTER( DSS_SYSCONFIG, 0x00000010 ); // Display Subsystem reset + while ( !( GET_REGISTER( DISPC_SYSSTATUS ) & 1 ) ); // Spin until reset complete + + TInt8 MIDLEMODE = 0x2; // Smart Standby. MStandby is asserted based on the internal activity of the module. + TInt8 CLOCKACTIVITY = 0x0; // interface and functional clocks can be switched off. + TInt8 SIDLEMODE = 0x2; // Smart idle. Idle request is acknowledged based on the internal activity of the module + TInt8 ENWAKEUP = 0x1; // Wakeup is enabled. + TInt8 SOFTRESET = 0x0; // Normal mode + TInt8 AUTOIDLE = 0x1; // Automatic L3 and L4 interface clock gating strategy is applied based on interface activity + l = MIDLEMODE<<12 | CLOCKACTIVITY<<8 | SIDLEMODE<<3 | ENWAKEUP<<2 | SOFTRESET<<1 | AUTOIDLE; + SET_REGISTER( DISPC_SYSCONFIG, l ); + + TInt8 LOADMOAD = 0x2; //Frame data only loaded every frame + l = LOADMOAD<<1; + SET_REGISTER( DISPC_CONFIG, l ); + + SET_REGISTER( DISPC_DEFAULT_COLOR0, 0xFFFFFFFF ); + SET_REGISTER( DISPC_TRANS_COLOR0, 0x00000000 ); + + TUint8 hbp = H_BPORCH - 1; // Horizontal Back Porch + TUint8 hfp = H_FPORCH - 1; // Horizontal front porch + TUint8 hsw = H_SYNC - 1; // Horizontal synchronization pulse width + if ( hsw > 63 ) + { + hsw = 63; + Kern::Printf("[LCD] H_SYNC too big"); + } + l = hbp<<20 | hfp<<8 | hsw; + SET_REGISTER( DISPC_TIMING_H, l ); + + TUint8 vbp = V_BPORCH; // Vertical back porch + TUint8 vfp = V_FPORCH; // Vertical front porch + TUint8 vsw = V_SYNC; // Vertical synchronization pulse width + __ASSERT_ALWAYS( vbp<=255, Kern::Fault("LCD", 1) ); + __ASSERT_ALWAYS( vfp<=255, Kern::Fault("LCD", 1) ); + __ASSERT_ALWAYS( vsw>=1 && vsw<=255, Kern::Fault("LCD", 1) ); + l = vbp<<20 | vfp<<8 | vsw; + SET_REGISTER( DISPC_TIMING_V, l ); + + TUint8 onoff= 0; + TUint8 rf = 0; + TUint8 ieo = 0; + TUint8 ipc = 1; // Invert Pixel Clock + TUint8 ihs = H_SYNC_POL ? 0 : 1; // Invert HSYNC (0: Positive Sync polarity, 1: Negative Sync polarity) + TUint8 ivs = V_SYNC_POL ? 0 : 1; // Invert VSYNC (0: Positive Sync polarity, 1: Negative Sync polarity) + TUint8 acbi = 0; + TUint16 acb = 0x28; // AC-bias pin frequency + l = onoff<<17 | rf<<16 | ieo<<15 | ipc<<14 | ihs<<13 | ivs<<12 | acbi<<8 | acb; + SET_REGISTER( DISPC_POL_FREQ, l ); + + TUint8 lcd = 1; // Display Controller Logic Clock Divisor + TUint8 pcd = ( 432000 + (PIXEL_CLK - 1) ) / PIXEL_CLK; // Pixel Clock Divisor - add (PIXEL_CLK - 1) to avoid rounding error + __ASSERT_ALWAYS( lcd>=1 && lcd<=255, Kern::Fault("LCD", 1) ); + __ASSERT_ALWAYS( pcd>=2 && pcd<=255, Kern::Fault("LCD", 1) ); + l = lcd<<16 | pcd; + SET_REGISTER( DISPC_DIVISOR, l ); + + TUint16 ppl = H_DISP - 1; // Pixels per line + TUint16 llp = V_DISP - 1; // Lines per panel + __ASSERT_ALWAYS( ppl>=1 && ppl<=2048, Kern::Fault("LCD", 1) ); + __ASSERT_ALWAYS( llp>=1 && llp<=2048, Kern::Fault("LCD", 1) ); + l = llp<<16 | ppl; + SET_REGISTER( DISPC_SIZE_LCD, l ); + + + // Setup a graphics region (GFX) + + // Set GFX frame buffer + SET_REGISTER( DISPC_GFX_BA1, ivRamPhys ); + + // Center the GFX + TInt16 gfxposy = ( V_DISP - KConfigLcdHeight ) / 2; + TInt16 gfxposx = ( H_DISP - KConfigLcdWidth ) / 2; + l = ( gfxposy << 16 ) | gfxposx; + SET_REGISTER( DISPC_GFX_POSITION, l ); + + // Set the GFX dimensions + TInt16 gfxsizey = KConfigLcdHeight - 1; + TInt16 gfxsizex = KConfigLcdWidth - 1; + l = gfxsizey<<16 | gfxsizex; + SET_REGISTER( DISPC_GFX_SIZE, l ); + + TInt8 GFXSELFREFRESH = 0x0; + TInt8 GFXARBITRATION = 0x0; + TInt8 GFXROTATION = 0x0; + TInt8 GFXFIFOPRELOAD = 0x0; + TInt8 GFXENDIANNESS = 0x0; + TInt8 GFXNIBBLEMODE = 0x0; + TInt8 GFXCHANNELOUT = 0x0; + TInt8 GFXBURSTSIZE = 0x2; // 16x32bit bursts + TInt8 GFXREPLICATIONENABLE = 0x0; // Disable Graphics replication logic + TInt8 GFXFORMAT = 0x6; // RGB16=0x6, RGB24-unpacked=0x8, RGB24-packed=0x9 + TInt8 GFXENABLE = 0x1; // Graphics enabled + l = GFXSELFREFRESH<<15 | GFXARBITRATION<<14 | GFXROTATION<<12 | GFXFIFOPRELOAD<<11 | GFXENDIANNESS<<10 | GFXNIBBLEMODE<<9 | GFXCHANNELOUT<8 | GFXBURSTSIZE<<6 | GFXREPLICATIONENABLE<<5 | GFXFORMAT<<1 | GFXENABLE; + SET_REGISTER( DISPC_GFX_ATTRIBUTES, l ); + + TInt16 GFXFIFOHIGHTHRESHOLD = 0x3fc; // Graphics FIFO High Threshold + TInt16 GFXFIFOLOWTHRESHOLD = 0x3BC; // Graphics FIFO Low Threshold + l = GFXFIFOHIGHTHRESHOLD<<16 | GFXFIFOLOWTHRESHOLD; + SET_REGISTER(DISPC_GFX_FIFO_THRESHOLD, l); + + TInt16 GFXFIFOSIZE = 0x400; // Number of bytes defining the FIFO value + l = GFXFIFOSIZE; + SET_REGISTER(DISPC_GFX_FIFO_SIZE_STATUS, l); + + TInt32 GFXROWINC = 0x1; + l = GFXROWINC; + SET_REGISTER(DISPC_GFX_ROW_INC, l); + + TInt16 GFXPIXELINC = 0x1; + l = GFXPIXELINC; + SET_REGISTER(DISPC_GFX_PIXEL_INC, l); + + TInt32 GFXWINDOWSKIP = 0x0; + l = GFXWINDOWSKIP; + SET_REGISTER(DISPC_GFX_WINDOW_SKIP, l); + + // TO DO: Sort out the Gamma table + pallets + TInt32 GFXTABLEBA = 0x807ff000; + l = GFXTABLEBA; + SET_REGISTER(DISPC_GFX_TABLE_BA, l); + + + // Propigate all the shadowed registers + + TInt8 SPATIALTEMPORALDITHERINGFRAMES = 0; + TInt8 LCDENABLEPOL = 0; + TInt8 LCDENABLESIGNAL = 0; + TInt8 PCKFREEENABLE = 0; + TInt8 TDMUNUSEDBITS = 0; + TInt8 TDMCYCLEFORMAT = 0; + TInt8 TDMPARALLELMODE = 0; + TInt8 TDMENABLE = 0; + TInt8 HT = 0; + TInt8 GPOUT1 = 1; + TInt8 GPOUT0 = 1; + TInt8 GPIN1 = 0; + TInt8 GPIN0 = 0; + TInt8 OVERLAYOPTIMIZATION = 0; + TInt8 RFBIMODE = 0; + TInt8 SECURE = 0; + TInt8 TFTDATALINES = 0x3; + TInt8 STDITHERENABLE = 0; + TInt8 GODIGITAL = 1; + TInt8 GOLCD = 1; + TInt8 M8B = 0; + TInt8 STNTFT = 1; + TInt8 MONOCOLOR = 0; + TInt8 DIGITALENABLE = 1; + TInt8 LCDENABLE = 1; + l = SPATIALTEMPORALDITHERINGFRAMES<<30 | LCDENABLEPOL<<29 | LCDENABLESIGNAL<<28 | PCKFREEENABLE<<27 | + TDMUNUSEDBITS<<25 | TDMCYCLEFORMAT<<23 | TDMPARALLELMODE<<21 | TDMENABLE<<20 | HT<<17 | GPOUT1<<16 | + GPOUT0<<15 | GPIN1<<14 | GPIN0<<13 | OVERLAYOPTIMIZATION<<12 | RFBIMODE<<11 | SECURE<<10 | + TFTDATALINES<<8 | STDITHERENABLE<<7 | GODIGITAL<<6 | GOLCD<<5 | M8B<<4 | STNTFT<<3 | + MONOCOLOR<<2 | DIGITALENABLE<<1 | LCDENABLE; + NKern::Sleep(1); + SET_REGISTER(DISPC_CONTROL, l); + NKern::Sleep(1); + + } + + +/** +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_REGISTER(DISPC_CONTROL, 0); + + } + +/** +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 + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Splash SCreen +")); + TUint* pV=(TUint*)(iVideoInfo.iVideoAddress + iVideoInfo.iOffsetToFirstPixel); + __KTRACE_OPT(KEXTENSION,Kern::Printf("Splash SCreen FB @ %x",pV)); + + //Fill the framebuffer with bars + + for (TInt y = 0; y> 3); + + TUint16* px = reinterpret_cast(pV) + y*KConfigLcdWidth + x; + *px = rgb; + } + } + + __KTRACE_OPT(KEXTENSION,Kern::Printf("Splash SCreen -")); + } + + +/** +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<= 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) + { + TInt r=KErrNone; + switch(aFunction) + { + case EDisplayHalScreenInfo: + { + TPckgBuf 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: + __KTRACE_OPT(KEXTENSION,Kern::Printf("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: + __KTRACE_OPT(KEXTENSION,Kern::Printf("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() vPckg; + r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2); + if (KErrNone == r) + Kern::InfoCopy(*(TDes8*)a1,vPckg); + } + break; + + case EDisplayHalSpecifiedModeInfo: + { + TPckgBuf 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; + } + 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; + } +