]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/device-ti-proprietary-open.git/blob - omap5/sgx_src/eurasia_km/services4/srvkm/devices/sgx/sgxpower.c
SGX: Kernel side DDK source code for OMAP5
[android-sdk/device-ti-proprietary-open.git] / omap5 / sgx_src / eurasia_km / services4 / srvkm / devices / sgx / sgxpower.c
1 /*************************************************************************/ /*!
2 @Title          Device specific power routines
3 @Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4 @License        Dual MIT/GPLv2
6 The contents of this file are subject to the MIT license as set out below.
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
18 Alternatively, the contents of this file may be used under the terms of
19 the GNU General Public License Version 2 ("GPL") in which case the provisions
20 of GPL are applicable instead of those above.
22 If you wish to allow use of your version of this file only under the terms of
23 GPL, and not to allow others to use your version of this file under the terms
24 of the MIT license, indicate your decision by deleting the provisions above
25 and replace them with the notice and other provisions required by GPL as set
26 out in the file called "GPL-COPYING" included in this distribution. If you do
27 not delete the provisions above, a recipient may use your version of this file
28 under the terms of either the MIT license or GPL.
30 This License is also included in this distribution in the file called
31 "MIT-COPYING".
33 EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
34 PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
35 BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
36 PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
37 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
38 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 */ /**************************************************************************/
42 #include <stddef.h>
44 #include "sgxdefs.h"
45 #include "services_headers.h"
46 #include "sgxapi_km.h"
47 #include "sgx_mkif_km.h"
48 #include "sgxutils.h"
49 #include "pdump_km.h"
51 int powering_down = 0;
54 #if defined(SUPPORT_HW_RECOVERY)
55 static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE              *psDeviceNode,
56                                                                 SGX_TIMING_INFORMATION  *psSGXTimingInfo,
57                                                                 IMG_HANDLE                              *phTimer)
58 {
59         /*
60                 Install timer callback for HW recovery at 50 times lower
61                 frequency than the microkernel timer.
62         */
63         *phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
64                                                   1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
65         if(*phTimer == IMG_NULL)
66         {
67                 PVR_DPF((PVR_DBG_ERROR,"SGXAddTimer : Failed to register timer callback function"));
68                 return PVRSRV_ERROR_OUT_OF_MEMORY;
69         }
71         return PVRSRV_OK;
72 }
73 #endif /* SUPPORT_HW_RECOVERY*/
76 /*!
77 ******************************************************************************
79  @Function      SGXUpdateTimingInfo
81  @Description
83         Derives the microkernel timing info from the system-supplied values
85  @Input    psDeviceNode : SGX Device node
87  @Return   PVRSRV_ERROR :
89 ******************************************************************************/
90 static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE      *psDeviceNode)
91 {
92         PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
93 #if defined(SGX_DYNAMIC_TIMING_INFO)
94         SGX_TIMING_INFORMATION  sSGXTimingInfo = {0};
95 #else
96         SGX_DEVICE_MAP          *psSGXDeviceMap;
97 #endif
98         IMG_UINT32              ui32ActivePowManSampleRate;
99         SGX_TIMING_INFORMATION  *psSGXTimingInfo;
102 #if defined(SGX_DYNAMIC_TIMING_INFO)
103         psSGXTimingInfo = &sSGXTimingInfo;
104         SysGetSGXTimingInformation(psSGXTimingInfo);
105 #else
106         SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
107                                                   (IMG_VOID**)&psSGXDeviceMap);
108         psSGXTimingInfo = &psSGXDeviceMap->sTimingInfo;
109 #endif
111 #if defined(SUPPORT_HW_RECOVERY)
112         {
113                 PVRSRV_ERROR                    eError;
114                 IMG_UINT32      ui32OlduKernelFreq;
116                 if (psDevInfo->hTimer != IMG_NULL)
117                 {
118                         ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
119                         if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
120                         {
121                                 /*
122                                         The ukernel timer frequency has changed.
123                                 */
124                                 IMG_HANDLE hNewTimer;
125                                 
126                                 eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
127                                 if (eError == PVRSRV_OK)
128                                 {
129                                         eError = OSRemoveTimer(psDevInfo->hTimer);
130                                         if (eError != PVRSRV_OK)
131                                         {
132                                                 PVR_DPF((PVR_DBG_ERROR,"SGXUpdateTimingInfo: Failed to remove timer"));
133                                         }
134                                         psDevInfo->hTimer = hNewTimer;
135                                 }
136                                 else
137                                 {
138                                         /* Failed to allocate the new timer, leave the old one. */
139                                 }
140                         }
141                 }
142                 else
143                 {
144                         eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &psDevInfo->hTimer);
145                         if (eError != PVRSRV_OK)
146                         {
147                                 return eError;
148                         }
149                 }
151                 psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
152                         psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
153         }
154 #endif /* SUPPORT_HW_RECOVERY*/
156         /* Copy the SGX clock speed for use in the kernel */
157         psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
158         psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
160         /* FIXME: no need to duplicate - remove it from psDevInfo */
161         psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
162 #if defined(PDUMP)
163         PDUMPCOMMENT("Host Control - Microkernel clock");
164         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
165                          offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
166                          sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
167                          MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
168 #endif /* PDUMP */
170         if (psSGXTimingInfo->bEnableActivePM)
171         {
172                 ui32ActivePowManSampleRate =
173                         psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
174                 /*
175                         ui32ActivePowerCounter has the value 0 when SGX is not idle.
176                         When SGX becomes idle, the value of ui32ActivePowerCounter is changed from 0 to ui32ActivePowManSampleRate.
177                         The ukernel timer routine decrements the value of ui32ActivePowerCounter if it is not 0.
178                         When the ukernel timer decrements ui32ActivePowerCounter from 1 to 0, the ukernel timer will
179                                 request power down.
180                         Therefore the minimum value of ui32ActivePowManSampleRate is 1.
181                 */
182                 ui32ActivePowManSampleRate += 1;
183         }
184         else
185         {
186                 ui32ActivePowManSampleRate = 0;
187         }
189         psDevInfo->psSGXHostCtl->ui32ActivePowManSampleRate = ui32ActivePowManSampleRate;
190 #if defined(PDUMP)
191         PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
192                          offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
193                          sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
194                          MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
195 #endif /* PDUMP */
197         return PVRSRV_OK;
201 /*!
202 ******************************************************************************
204  @Function      SGXStartTimer
206  @Description
208         Start the microkernel timer
210  @Input    psDevInfo : SGX Device Info
212  @Return   IMG_VOID :
214 ******************************************************************************/
215 static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO        *psDevInfo)
217         #if defined(SUPPORT_HW_RECOVERY)
218         PVRSRV_ERROR    eError;
220         eError = OSEnableTimer(psDevInfo->hTimer);
221         if (eError != PVRSRV_OK)
222         {
223                 PVR_DPF((PVR_DBG_ERROR,"SGXStartTimer : Failed to enable host timer"));
224         }
225         #else
226         PVR_UNREFERENCED_PARAMETER(psDevInfo);
227         #endif /* SUPPORT_HW_RECOVERY */
231 /*!
232 ******************************************************************************
234  @Function      SGXPollForClockGating
236  @Description
238         Wait until the SGX core clocks have gated.
240  @Input    psDevInfo : SGX Device Info
241  @Input    ui32Register : Offset of register to poll
242  @Input    ui32Register : Value of register to poll for
243  @Input    pszComment : Description of poll
245  @Return   IMG_VOID :
247 ******************************************************************************/
248 static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO       *psDevInfo,
249                                                                            IMG_UINT32                   ui32Register,
250                                                                            IMG_UINT32                   ui32RegisterValue,
251                                                                            IMG_CHAR                             *pszComment)
253         PVR_UNREFERENCED_PARAMETER(psDevInfo);
254         PVR_UNREFERENCED_PARAMETER(ui32Register);
255         PVR_UNREFERENCED_PARAMETER(ui32RegisterValue);
256         PVR_UNREFERENCED_PARAMETER(pszComment);
258         #if !defined(NO_HARDWARE)
259         PVR_ASSERT(psDevInfo != IMG_NULL);
261         /* PRQA S 0505 1 */ /* QAC does not like assert() */
262         if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
263                                                 0,
264                                                 ui32RegisterValue,
265                                                 MAX_HW_TIME_US,
266                                                 MAX_HW_TIME_US/WAIT_TRY_COUNT,
267                                                 IMG_FALSE) != PVRSRV_OK)
268         {
269                 PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
270                 SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
271                 PVR_DBG_BREAK;
272         }
273         #endif /* NO_HARDWARE */
275         PDUMPCOMMENT("%s", pszComment);
276         PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL);
280 /*!
281 ******************************************************************************
283  @Function      SGXPrePowerState
285  @Description
287  does necessary preparation before power state transition
289  @Input    hDevHandle : SGX Device Node
290  @Input    eNewPowerState : New power state
291  @Input    eCurrentPowerState : Current power state
293  @Return   PVRSRV_ERROR :
295 ******************************************************************************/
296 PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE                               hDevHandle,
297                                                            PVRSRV_DEV_POWER_STATE       eNewPowerState,
298                                                            PVRSRV_DEV_POWER_STATE       eCurrentPowerState)
300         if ((eNewPowerState != eCurrentPowerState) &&
301                 (eNewPowerState != PVRSRV_DEV_POWER_STATE_ON))
302         {
303                 PVRSRV_ERROR            eError;
304                 PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
305                 PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
306                 IMG_UINT32                      ui32PowerCmd, ui32CompleteStatus;
307                 SGXMKIF_COMMAND         sCommand = {0};
308                 IMG_UINT32                      ui32Core;
309                 IMG_UINT32                      ui32CoresEnabled;
311                 #if defined(SUPPORT_HW_RECOVERY)
312                 /* Disable timer callback for HW recovery */
313                 eError = OSDisableTimer(psDevInfo->hTimer);
314                 if (eError != PVRSRV_OK)
315                 {
316                         PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
317                         return eError;
318                 }
319                 #endif /* SUPPORT_HW_RECOVERY */
321                 if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
322                 {
323                         /* Request the ukernel to idle SGX and save its state. */
324                         ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
325                         ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
326                         PDUMPCOMMENT("SGX power off request");
327                 }
328                 else
329                 {
330                         /* Request the ukernel to idle SGX. */
331                         ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
332                         ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
333                         PDUMPCOMMENT("SGX idle request");
334                 }
336                 powering_down = 1;
338                 sCommand.ui32Data[1] = ui32PowerCmd;
340                 eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
341                 if (eError != PVRSRV_OK)
342                 {
343                         PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to submit power down command"));
344                         return eError;
345                 }
347                 /* Wait for the ukernel to complete processing. */
348                 #if !defined(NO_HARDWARE)
349                 if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
350                                                         ui32CompleteStatus,
351                                                         ui32CompleteStatus,
352                                                         MAX_HW_TIME_US,
353                                                         MAX_HW_TIME_US/WAIT_TRY_COUNT,
354                                                         IMG_FALSE) != PVRSRV_OK)
355                 {
356                         PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
357                         SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
358                         PVR_DBG_BREAK;
359                 }
360                 #endif /* NO_HARDWARE */
362                 if (psDevInfo->bSGXIdle == IMG_FALSE)
363                 {
364                         psDevInfo->bSGXIdle = IMG_TRUE;
365                         SysSGXIdleEntered();
366                 }
368                 #if defined(PDUMP)
369                 PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
370                 PDUMPMEMPOL(psDevInfo->psKernelSGXHostCtlMemInfo,
371                                         offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
372                                         ui32CompleteStatus,
373                                         ui32CompleteStatus,
374                                         PDUMP_POLL_OPERATOR_EQUAL,
375                                         0,
376                                         MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
377                 #endif /* PDUMP */
379 #if defined(SGX_FEATURE_MP)
380                 ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1;
381 #else
382                 ui32CoresEnabled = 1;
383 #endif
385                 for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++)
386                 {
387                         /* Wait for SGX clock gating. */
388                         SGXPollForClockGating(psDevInfo,
389                                                                   SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
390                                                                   psDevInfo->ui32ClkGateStatusMask,
391                                                                   "Wait for SGX clock gating");
392                 }
394                 #if defined(SGX_FEATURE_MP)
395                 /* Wait for SGX master clock gating. */
396                 SGXPollForClockGating(psDevInfo,
397                                                           psDevInfo->ui32MasterClkGateStatusReg,
398                                                           psDevInfo->ui32MasterClkGateStatusMask,
399                                                           "Wait for SGX master clock gating");
401                 SGXPollForClockGating(psDevInfo,
402                                                           psDevInfo->ui32MasterClkGateStatus2Reg,
403                                                           psDevInfo->ui32MasterClkGateStatus2Mask,
404                                                           "Wait for SGX master clock gating (2)");
405                 #endif /* SGX_FEATURE_MP */
407                 if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
408                 {
409                         /* Finally, de-initialise some registers. */
410                         eError = SGXDeinitialise(psDevInfo);
411                         if (eError != PVRSRV_OK)
412                         {
413                                 PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: SGXDeinitialise failed: %u", eError));
414                                 return eError;
415                         }
416                 }
417         }
419         return PVRSRV_OK;
423 /*!
424 ******************************************************************************
426  @Function      SGXPostPowerState
428  @Description
430  does necessary preparation after power state transition
432  @Input    hDevHandle : SGX Device Node
433  @Input    eNewPowerState : New power state
434  @Input    eCurrentPowerState : Current power state
436  @Return   PVRSRV_ERROR :
438 ******************************************************************************/
439 PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE                              hDevHandle,
440                                                                 PVRSRV_DEV_POWER_STATE  eNewPowerState,
441                                                                 PVRSRV_DEV_POWER_STATE  eCurrentPowerState)
443         if ((eNewPowerState != eCurrentPowerState) &&
444                 (eCurrentPowerState != PVRSRV_DEV_POWER_STATE_ON))
445         {
446                 PVRSRV_ERROR            eError;
447                 PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
448                 PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
449                 SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
451                 /* Reset the power manager flags. */
452                 psSGXHostCtl->ui32PowerStatus = 0;
453                 #if defined(PDUMP)
454                 PDUMPCOMMENT("Host Control - Reset power status");
455                 PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
456                                  offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
457                                  sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
458                                  MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
459                 #endif /* PDUMP */
461                 if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
462                 {
463                         /*
464                                 Coming up from off, re-initialise SGX.
465                         */
467                         /*
468                                 Re-generate the timing data required by SGX.
469                         */
470                         eError = SGXUpdateTimingInfo(psDeviceNode);
471                         if (eError != PVRSRV_OK)
472                         {
473                                 PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
474                                 return eError;
475                         }
477                         /*
478                                 Run the SGX init script.
479                         */
480                         eError = SGXInitialise(psDevInfo, IMG_FALSE);
481                         if (eError != PVRSRV_OK)
482                         {
483                                 PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXInitialise failed"));
484                                 return eError;
485                         }
486                         powering_down = 0;
487                 }
488                 else
489                 {
490                         /*
491                                 Coming up from idle, restart the ukernel.
492                         */
493                         SGXMKIF_COMMAND         sCommand = {0};
495                         sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
496                         eError = SGXScheduleCCBCommand(psDeviceNode, SGXMKIF_CMD_POWER, &sCommand, ISR_ID, 0, IMG_NULL, IMG_FALSE);
497                         if (eError != PVRSRV_OK)
498                         {
499                                 PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState failed to schedule CCB command: %u", eError));
500                                 return eError;
501                         }
502                 }
504                 SGXStartTimer(psDevInfo);
505         }
507         return PVRSRV_OK;
511 /*!
512 ******************************************************************************
514  @Function      SGXPreClockSpeedChange
516  @Description
518         Does processing required before an SGX clock speed change.
520  @Input    hDevHandle : SGX Device Node
521  @Input    bIdleDevice : Whether the microkernel needs to be idled
522  @Input    eCurrentPowerState : Power state of the device
524  @Return   PVRSRV_ERROR :
526 ******************************************************************************/
527 PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE                         hDevHandle,
528                                                                          IMG_BOOL                               bIdleDevice,
529                                                                          PVRSRV_DEV_POWER_STATE eCurrentPowerState)
531         PVRSRV_ERROR            eError;
532         PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
533         PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
535         PVR_UNREFERENCED_PARAMETER(psDevInfo);
537         if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
538         {
539                 if (bIdleDevice)
540                 {
541                         /*
542                          * Idle SGX.
543                          */
544                         PDUMPSUSPEND();
546                         eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
547                                                                           PVRSRV_DEV_POWER_STATE_ON);
549                         if (eError != PVRSRV_OK)
550                         {
551                                 PDUMPRESUME();
552                                 return eError;
553                         }
554                 }
555         }
557         PVR_DPF((PVR_DBG_MESSAGE,"SGXPreClockSpeedChange: SGX clock speed was %uHz",
558                         psDevInfo->ui32CoreClockSpeed));
560         return PVRSRV_OK;
564 /*!
565 ******************************************************************************
567  @Function      SGXPostClockSpeedChange
569  @Description
571         Does processing required after an SGX clock speed change.
573  @Input    hDevHandle : SGX Device Node
574  @Input    bIdleDevice : Whether the microkernel had been idled previously
575  @Input    eCurrentPowerState : Power state of the device
577  @Return   PVRSRV_ERROR :
579 ******************************************************************************/
580 PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE                                hDevHandle,
581                                                                           IMG_BOOL                                      bIdleDevice,
582                                                                           PVRSRV_DEV_POWER_STATE        eCurrentPowerState)
584         PVRSRV_DEVICE_NODE      *psDeviceNode = hDevHandle;
585         PVRSRV_SGXDEV_INFO      *psDevInfo = psDeviceNode->pvDevice;
586         IMG_UINT32                      ui32OldClockSpeed = psDevInfo->ui32CoreClockSpeed;
588         PVR_UNREFERENCED_PARAMETER(ui32OldClockSpeed);
590         if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_ON)
591         {
592                 PVRSRV_ERROR eError;
594                 /*
595                         Re-generate the timing data required by SGX.
596                 */
597                 eError = SGXUpdateTimingInfo(psDeviceNode);
598                 if (eError != PVRSRV_OK)
599                 {
600                         PVR_DPF((PVR_DBG_ERROR,"SGXPostPowerState: SGXUpdateTimingInfo failed"));
601                         return eError;
602                 }
604                 if (bIdleDevice)
605                 {
606                         /*
607                          * Resume SGX.
608                          */
609                         eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
610                                                                            PVRSRV_DEV_POWER_STATE_IDLE);
612                         PDUMPRESUME();
614                         if (eError != PVRSRV_OK)
615                         {
616                                 return eError;
617                         }
618                 }
619                 else
620                 {
621                         SGXStartTimer(psDevInfo);
622                 }
623         }
625         PVR_DPF((PVR_DBG_MESSAGE,"SGXPostClockSpeedChange: SGX clock speed changed from %uHz to %uHz",
626                         ui32OldClockSpeed, psDevInfo->ui32CoreClockSpeed));
628         return PVRSRV_OK;
632 /******************************************************************************
633  End of file (sgxpower.c)
634 ******************************************************************************/