Adaptation/GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9.dita
changeset 15 307f4279f433
equal deleted inserted replaced
14:578be2adaf3e 15:307f4279f433
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9" xml:lang="en"><title>LCD Extension Implementation Tutorial</title><shortdesc>This topic describes how to create an LCD Extension.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    13 <p>The topic uses a reference board port named <filepath>template_variant</filepath> as an example implementation. </p>
       
    14 <section id="GUID-7DDD91D2-A69F-4940-AA58-74EB2A989E55"><title>Build
       
    15 environment</title> <p>In the template reference board port, the <filepath>.mmp</filepath> file for the LCD Extension is <filepath>...\template_variant\lcdtemplate.mmp</filepath>. This is one of the <codeph>PRJ_MMPFILES</codeph> referenced in
       
    16 the template variant's <filepath>bld.inf</filepath> file in the <filepath>...\template_variant\...</filepath> directory, and means that the
       
    17 LCD Extension is built as part of the Variant. </p> <p>The source
       
    18 for the driver is contained entirely within <filepath>...\template_variant\specific\lcd.cpp</filepath>. </p> <p>The driver is defined as a kernel extension and is loaded
       
    19 early in the boot sequence. </p> </section>
       
    20 <section id="GUID-FC49B296-5DFA-4C19-BEDE-F641D70E5ED9"><title>Initialization</title> <p>The driver functionality is almost entirely encapsulated by the <codeph>DLcdPowerHandler</codeph> class. This is a power handler class derived
       
    21 from <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita"><apiname>DPowerHandler</apiname></xref>. An instance of <codeph>DLcdPowerHandler</codeph> is created when the extension is loaded. </p> <p> <codeph>DLcdPowerHandler</codeph> is defined within the source file itself <filepath>...\template_variant\specific\lcd.cpp</filepath>. </p> <p>As the driver is a kernel extension, it must have a <codeph>DECLARE_STANDARD_EXTENSION()</codeph> statement. In the template
       
    22 port, this is implemented as follows: </p> <codeblock id="GUID-BB93E7E7-06DA-5A12-ABA1-D07AA246D6FC" xml:space="preserve">DECLARE_STANDARD_EXTENSION()
       
    23     {
       
    24     __KTRACE_OPT(KPOWER,Kern::Printf("Starting LCD power manager"));
       
    25     
       
    26     // create LCD power handler
       
    27     TInt r=KErrNoMemory;
       
    28     DLcdPowerHandler* pH=new DLcdPowerHandler;
       
    29     if (pH)
       
    30         r=pH-&gt;Create();
       
    31     
       
    32     __KTRACE_OPT(KPOWER,Kern::Printf("Returns %d",r));
       
    33     return r;
       
    34     }
       
    35 </codeblock> <p>This simply creates an instance of the <codeph>DLcdPowerHandler</codeph> class and then calls its <codeph>Create()</codeph> function which
       
    36 implements the display setup. This function should do the following: </p> <ul>
       
    37 <li id="GUID-4D3B36C6-C782-5B3F-8244-7FD33B9976C6"><p>map the video
       
    38 RAM </p> </li>
       
    39 <li id="GUID-B693BD2B-50FF-554D-AF2B-1992A472F586"><p>setup the video
       
    40 info structure </p> </li>
       
    41 <li id="GUID-1DF67FC0-90FA-5853-88C2-6DBA5C60F377"><p>install the
       
    42 HAL handler </p> </li>
       
    43 <li id="GUID-2B8080C4-2A9F-5AA2-B609-3DC8F5759DDE"><p>install the
       
    44 power handler. </p> </li>
       
    45 </ul> <p><b> Map the video RAM</b> </p> <p>The frame buffer is a <xref href="GUID-2A34A3DD-A7FE-34A0-B0B7-BB0A4F04B098.dita"><apiname>DPlatChunkHw</apiname></xref> object, and should be mapped as globally accessible,
       
    46 readable and writeable. It should <i>not</i> be mapped as writeback
       
    47 cached, it should be either not-cached or write-through. The advantage
       
    48 of write through is that it allows the use of the write buffer. </p> <codeblock id="GUID-148795D9-45A2-526B-A2F7-57B5B2AAC8AB" xml:space="preserve">TInt DLcdPowerHandler::Create()
       
    49     {
       
    50     ...
       
    51 
       
    52     // map the video RAM
       
    53     TInt vSize = ((TemplateAssp*)Arch::TheAsic())-&gt;VideoRamSize();
       
    54     ivRamPhys = TTemplate::VideoRamPhys();                // EXAMPLE ONLY: assume TTemplate interface class
       
    55     TInt r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
       
    56     if ® != KErrNone)
       
    57         return r;
       
    58  ...
       
    59 </codeblock> <p>If the frame buffer resides in main RAM and there
       
    60 is no restriction on which physical addresses may be used for it,
       
    61 physical RAM for the frame buffer should be reserved by using <xref href="GUID-3DC7B5F2-512E-3FF3-BC08-945DDE2AE680.dita#GUID-3DC7B5F2-512E-3FF3-BC08-945DDE2AE680/GUID-B506D835-505D-3D89-A840-475F291908DC"><apiname>Epoc::AllocPhysicalRam()</apiname></xref>. </p> <p>If the frame buffer does
       
    62 not reside in main RAM, there is no problem about reserving it. </p> <p>If the frame buffer must reside at a specific address in main
       
    63 RAM, there are two strategies available for reserving it: </p> <ul>
       
    64 <li id="GUID-29D3BF5F-442B-5912-A8B9-4F1F76C1879E"><p>If no conflicts
       
    65 are permitted between the frame buffer and memory allocations made
       
    66 during the kernel boot (for example, if the frame buffer must reside
       
    67 at the end of main memory), simply use <xref href="GUID-3DC7B5F2-512E-3FF3-BC08-945DDE2AE680.dita#GUID-3DC7B5F2-512E-3FF3-BC08-945DDE2AE680/GUID-78F136DC-023B-30AB-A1AB-34D6BC4F1B3E"><apiname>Epoc::ClaimPhysicalRam()</apiname></xref>. This function just marks a region of physical RAM as allocated,
       
    68 returning an error if any part of the region has already been used. </p> </li>
       
    69 <li id="GUID-F2C5ED3A-767A-58CA-BDC6-78D3C1820C80"><p>The required
       
    70 physical RAM region can be reserved in the bootstrap. The correct
       
    71 place to do this is in the implementation of the boot table function <xref href="GUID-B3F6FC45-3BF0-5F92-8325-44C705BA47AE.dita#GUID-B3F6FC45-3BF0-5F92-8325-44C705BA47AE/GUID-B3C6ACE9-A803-59D4-8EBD-314363905427">BTF_Reserve</xref> when writing platform-specific source code for
       
    72 the bootstrap. See the Bootstrap <xref href="GUID-5EB03086-A87D-5588-8927-7A7F8DB38366.dita">Port Implementation
       
    73 Tutorial</xref> for more detail and look at <filepath>...\template_variant\bootstrap\template.s</filepath> for a concrete example. </p> </li>
       
    74 </ul> <p>Note that all Symbian platform base ports currently create
       
    75 a second frame buffer for a secure screen. However, as platform security
       
    76 is not yet implemented, this is wasteful of RAM and should be omitted. </p> <p id="GUID-57223C8C-0381-51AC-8E8A-771434136A5C"><b> Set up the video
       
    77 information structure</b> </p> <p>The video information structure
       
    78 is used to define several aspects of the display including display
       
    79 size, bits per pixel and address of the frame buffer. This structure
       
    80 is the class <xref href="GUID-C4712A78-6C58-39ED-AF84-11038DB8571D.dita"><apiname>TVideoInfoV01</apiname></xref> defined in the header
       
    81 file <filepath>...\eka\include\videodriver.h</filepath> and exported
       
    82 to <filepath>...\epoc32\include</filepath>. </p> <codeblock id="GUID-0680E467-9552-5FD6-BBDE-60AE95F0B941" xml:space="preserve">TInt DLcdPowerHandler::Create()
       
    83     {
       
    84        ...
       
    85        // setup the video info structure, this will be used to remember the video settings
       
    86        iVideoInfo.iDisplayMode = KConfigLcdInitialDisplayMode;
       
    87        iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetToFirstVideoBuffer;
       
    88        iVideoInfo.iIsPalettized = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iIsPalettized;
       
    89        iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetBetweenLines;
       
    90        iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iBitsPerPixel;
       
    91 
       
    92        iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth;
       
    93        iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
       
    94        iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
       
    95        iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
       
    96        iVideoInfo.iIsMono = KConfigLcdIsMono;
       
    97        iVideoInfo.iVideoAddress=(TInt)pV;
       
    98        iVideoInfo.iIsPixelOrderLandscape = KConfigLcdPixelOrderLandscape;
       
    99        iVideoInfo.iIsPixelOrderRGB = KConfigLcdPixelOrderRGB;
       
   100     ...
       
   101     }</codeblock> <p><b> Install the HAL handler</b> </p> <p>Control of the display is
       
   102 done by using the HAL, the Hardware Abstraction Layer. </p> <p>The <codeph>DLcdPowerHandler</codeph> class provides the implementation for the
       
   103 HAL handler for the HAL function group <xref href="GUID-7F299BFC-D8A5-3A5A-B8DA-39BF42C99DC6.dita"><apiname>EHalGroupDisplay</apiname></xref> and this needs to be registered with the kernel by calling <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-8C8DCE9D-0094-3909-8FDA-2F3134D0BC88"><apiname>Kern::AddHalEntry()</apiname></xref>. </p> <codeblock id="GUID-F9E86404-742D-5931-BA77-DA246A3975E5" xml:space="preserve">TInt DLcdPowerHandler::Create()
       
   104     {
       
   105        ...
       
   106        // install the HAL function
       
   107        r=Kern::AddHalEntry(EHalGroupDisplay, halFunction, this);
       
   108        if (r!=KErrNone)
       
   109               return r;
       
   110     ...
       
   111     }</codeblock> <p>See <xref href="GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8.dita#GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8/GUID-4DA41221-40B9-5BC7-B2C6-7C6EB4522508">User-Side Hardware Abstraction</xref> for more detailed information
       
   112 on the HAL. </p> <p><b> Install the power handler</b> </p> <p>A call must be made to
       
   113 the <codeph>Add()</codeph> function, which is supplied by the <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita"><apiname>DPowerHandler</apiname></xref> base class of <codeph>DLcdPowerHandler</codeph>, to register the handler with the power manager. </p> <codeblock id="GUID-9286C3A2-DC2B-54F1-9F28-4EBE085AEE84" xml:space="preserve">TInt DLcdPowerHandler::Create()
       
   114     {
       
   115        ...
       
   116         // install the power handler
       
   117         // power up the screen
       
   118         Add();
       
   119     ...
       
   120     }</codeblock> </section>
       
   121 <section id="GUID-85B93308-2EDF-462C-8F64-6AE40B8B16B6"><title>HAL
       
   122 handler implementation</title> <p>Requests to get and set hardware
       
   123 attributes are made through calls to <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> and <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-9454F1B2-D525-3D6D-A872-C6457CACD4FC"><apiname>HAL::Set()</apiname></xref>. These two HAL functions take
       
   124 a value that identifies a hardware attribute, one of the <xref href="GUID-8BE90160-2C60-3582-82C8-4A108C7C0317.dita#GUID-8BE90160-2C60-3582-82C8-4A108C7C0317/GUID-1959915A-BA99-3F94-AFD4-FD1AA540BFBF"><apiname>HALData::TAttribute</apiname></xref> values. </p> <p>For the LCD Extension,
       
   125 the relevant hardware attributes are: <codeph>EDisplayMode</codeph>, <codeph>EDisplayBitsPerPixel</codeph>, <codeph>EDisplayIsPalettized</codeph>, <codeph>EDisplayIsMono</codeph>, <codeph>EDisplayMemoryAddress</codeph>, <codeph>EDisplayMemoryHandle</codeph>, <codeph>EDisplayOffsetToFirstPixel</codeph>, <codeph>EDisplayOffsetBetweenLines</codeph>, <codeph>EDisplayXPixels</codeph>, <codeph>EDisplayYPixels</codeph>, <codeph>EDisplayPaletteEntry</codeph> and <codeph>EDisplayOffsetBetweenLines</codeph>. </p> <p>The HAL
       
   126 handler is registered with the kernel as the handler for the <xref href="GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7.dita#GUID-66A851A0-2A0C-3624-AEC1-22F6629FABF7/GUID-950EA0D3-747F-305E-92EA-1579023A111E"><apiname>THalFunctionGroup::EHalGroupDisplay</apiname></xref> group. The HAL handler
       
   127 itself takes a function ID, which is one of the <xref href="GUID-BB011D9B-105F-345C-9FC0-39B0BA509394.dita"><apiname>TDisplayHalFunction</apiname></xref> enumerators. </p> <p>A call to <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-573C49D6-7763-37AE-B2B2-4C8FB1327E21"><apiname>HAL::Get()</apiname></xref> and <xref href="GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8.dita#GUID-BD00E7FC-C234-3111-87A5-10F79EB0F2B8/GUID-9454F1B2-D525-3D6D-A872-C6457CACD4FC"><apiname>HAL::Set()</apiname></xref> that takes one of the hardware attributes relevant
       
   128 to the LCD Extension is ultimately routed to a call to this HAL handler
       
   129 function passing an appropriate function ID. The association between
       
   130 the hardware attribute and the function ID is the responsibility of
       
   131 the accessor functions. </p> <p>See <xref href="GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8.dita#GUID-2D977A02-5928-5441-8AE7-42A722F2A4B8/GUID-4DA41221-40B9-5BC7-B2C6-7C6EB4522508">User-Side Hardware Abstraction</xref> for more information on the
       
   132 way this works in general. </p> <p>The HAL handler is implemented
       
   133 as a case statement, switching on the function ID. For example, the
       
   134 following code fragment taken from <codeph>DLcdPowerHandler::HalFunction()</codeph> gets and sets the brightness: </p> <codeblock id="GUID-41D5153A-107A-5FCC-9E51-C6250857F3AC" xml:space="preserve">TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
       
   135     {
       
   136     TInt r=KErrNone;
       
   137     switch(aFunction)
       
   138         {
       
   139     
       
   140         ...
       
   141          case EDisplayHalSetDisplayBrightness:
       
   142              if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,
       
   143        __PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayBrightness")))
       
   144                        return KErrPermissionDenied;
       
   145              r=SetBrightness(TInt(a1));
       
   146              break;
       
   147             
       
   148          case EDisplayHalDisplayBrightness:
       
   149              kumemput32(a1,&amp;iBrightness,sizeof(iBrightness));
       
   150              break;
       
   151         ...
       
   152 </codeblock> <p>where <codeph>SetBrightness()</codeph> is implemented
       
   153 as: </p> <codeblock id="GUID-82F38251-19A9-54BC-A066-80ED5AC549AF" xml:space="preserve">TInt DLcdPowerHandler::SetBrightness(TInt aValue)
       
   154     {
       
   155      __KTRACE_OPT(KEXTENSION,Kern::Printf("SetBrightness(%d)", aValue));
       
   156 
       
   157      if (aValue &gt;= KConfigLcdMinDisplayBrightness &amp;&amp; aValue &lt;= KConfigLcdMaxDisplayBrightness)
       
   158          {
       
   159          iBrightness=aValue;
       
   160     
       
   161          // TO DO: (mandatory)
       
   162          // set the brightness
       
   163          //
       
   164          return KErrNone;
       
   165          }
       
   166     return KErrArgument;
       
   167     }
       
   168 </codeblock> <p>If an attribute does not have an implementation, the
       
   169 HAL handler function should return <xref href="GUID-F89DA3F0-2A48-3F9B-8F08-29350E92D0E4.dita"><apiname>KErrNotSupported</apiname></xref>. </p> <p>For platform security, the code only allows the attribute
       
   170 to be set if the current thread has been authorized to write system
       
   171 data. Otherwise, it returns <xref href="GUID-213DE05E-24F7-3E94-9B35-F4A72B3EBFD8.dita"><apiname>KErrPermissionDenied</apiname></xref>. </p> <p><b>Switch on and switch off operations</b> </p> <p>All of the HAL
       
   172 operations are seen to be synchronous by the user side. However there
       
   173 are some operations such as turning the display on and off which may
       
   174 need to be implemented asynchronously. </p> <p>The display on/off
       
   175 code is implemented using synchronous kernel-side messages. There
       
   176 is only one message per thread and the thread always blocks while
       
   177 a message is outstanding. This means it is possible to make an asynchronous
       
   178 operation appear synchronous. </p> <p>When turning on the screen the
       
   179 kernel-side message is queued and this thread is blocked until the
       
   180 message is completed, which happens when the display has been turned
       
   181 on. </p> <p>If a display needs to be turned on and off truly asynchronously
       
   182 (for example, if millisecond timer waits are required during the process
       
   183 of turning on the display), the above functionality must be changed
       
   184 so that the complete occurs when the display is truly on. </p> <p><b>Accessing the video information structure</b> </p> <p>When any
       
   185 part of the <xref href="GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9.dita#GUID-6A4FE3A3-2E5D-51BB-8272-5995586291E9/GUID-57223C8C-0381-51AC-8E8A-771434136A5C">video information structure</xref> is read or written to, this must
       
   186 be done within a critical section to prevent potential collisions
       
   187 with other threads attempting to access the structure concurrently.
       
   188 A fast mutex is used to ensure that only one thread can access the
       
   189 video information at any one time, as the code segment below shows. </p> <codeblock id="GUID-E30D9790-109C-541F-A534-C92CBD4E1706" xml:space="preserve">TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01&amp; aInfo, TBool aSecure)
       
   190     {
       
   191      __KTRACE_OPT(KEXTENSION,Kern::Printf("GetCurrentDisplayModeInfo"));
       
   192      NKern::FMWait(&amp;iLock);
       
   193      if (aSecure)
       
   194           aInfo = iSecureVideoInfo;
       
   195      else
       
   196          aInfo = iVideoInfo;
       
   197      NKern::FMSignal(&amp;iLock);
       
   198      return KErrNone;
       
   199      }
       
   200 </codeblock> </section>
       
   201 <section id="GUID-04C06DAE-EE8E-4EE9-940F-807F82FBACD1"><title>Power
       
   202 handler implementation</title> <p>The <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita"><apiname>DPowerHandler</apiname></xref> class defines the interface that the driver must implement to provide
       
   203 power handling behaviour. For the template reference board, the LCD
       
   204 Extension defines and implements the <codeph>DLcdPowerHandler</codeph> class derived from <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita"><apiname>DPowerHandler</apiname></xref>. </p> <p> <b>Note</b>: </p> <ul>
       
   205 <li id="GUID-32D95977-F46B-50E0-B575-BE7369C05F62"><p> <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-578DB5FB-731D-36B2-A459-AAC7F250D726"><apiname>DPowerHandler::PowerDown()</apiname></xref> and <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-DDC564B4-BD12-30E9-B04A-DBA6CFAF8743"><apiname>DPowerHandler::PowerUp()</apiname></xref>  </p> <p>These functions
       
   206 are called in the context of the thread that initiates power down
       
   207 or power up, and synchronization is required, typically by means of
       
   208 power up and power down DFCs. </p> </li>
       
   209 <li id="GUID-7DC988A6-C60E-5951-9DD7-82DA129A8CB6"><p> <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-038F9D7D-7DA0-3299-8AA2-85F175206887"><apiname>DPowerHandler::PowerUpLcd()</apiname></xref> and <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-6EAF00D1-3CBA-3BC0-BAD9-7301EE5F9E12"><apiname>DPowerHandler::PowerDownLcd()</apiname></xref>  </p> <p>These
       
   210 functions generally queue DFCs which then call platform-specific functions
       
   211 to power the display up and down. </p> </li>
       
   212 <li id="GUID-51152EA7-C1A5-5AB3-8ACD-6FF6F16A255D"><p> <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-BF62042B-FB7B-3D5B-8379-490FBA284A7A"><apiname>DPowerHandler::PowerUpDone()</apiname></xref> and <xref href="GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7.dita#GUID-761AE02B-41A6-35EA-AA9F-0AEEFF67A6F7/GUID-EBE8CFF8-50BD-3AC3-A4C8-47094DA5674D"><apiname>DPowerHandler::PowerDownDone()</apiname></xref>  </p> <p>When
       
   213 power up or down is complete, the interface supplies a set of acknowledgment
       
   214 functions which must be called when the change of state has taken
       
   215 place. </p> </li>
       
   216 </ul> </section>
       
   217 </conbody><related-links>
       
   218 <link href="GUID-0C3A4156-E5CF-55F9-91A0-A7961FDEE030.dita"><linktext>LCD
       
   219 Extension Architecture</linktext></link>
       
   220 <link href="GUID-8DF46A11-874A-52E5-9298-C083EA633BA0.dita"><linktext>Implementing
       
   221 Dynamic DSA                 Allocation</linktext></link>
       
   222 </related-links></concept>