1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
30 #include "services_headers.h"
31 #include "buffer_manager.h"
32 #include "sgxapi_km.h"
34 #include "sgxinfokm.h"
35 #include "sysconfig.h"
36 #include "pvr_pdump.h"
38 #include "pvr_bridge_km.h"
39 #include "sgx_bridge_km.h"
41 #include "pvr_debug.h"
44 #include <linux/tty.h>
47 static void SGXPostActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode)
49 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
50 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
51 psDevInfo->psSGXHostCtl;
54 /* To aid in calculating the next power down delay */
55 sgx_mark_power_down(psDeviceNode);
57 l = readl(&psSGXHostCtl->ui32NumActivePowerEvents);
59 writel(l, &psSGXHostCtl->ui32NumActivePowerEvents);
61 l = readl(&psSGXHostCtl->ui32PowerStatus);
62 if (l & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE)
63 SGXScheduleProcessQueues(psDeviceNode);
66 void SGXTestActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode)
68 enum PVRSRV_ERROR eError = PVRSRV_OK;
69 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
70 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl = psDevInfo->psSGXHostCtl;
73 if (isSGXPerfServerActive())
76 l = readl(&psSGXHostCtl->ui32InterruptFlags);
77 if (!(l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER))
80 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
81 if (l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER)
84 /* Microkernel is idle and is requesting to be powered down. */
85 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
86 l |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
87 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
91 eError = PVRSRVSetDevicePowerStateKM(
92 psDeviceNode->sDevId.ui32DeviceIndex,
93 PVRSRV_POWER_STATE_D3);
94 if (eError == PVRSRV_OK)
95 SGXPostActivePowerEvent(psDeviceNode);
99 if (eError != PVRSRV_OK)
100 PVR_DPF(PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu",
104 static inline struct SGXMKIF_COMMAND *SGXAcquireKernelCCBSlot(
105 struct PVRSRV_SGX_CCB_INFO *psCCB)
107 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
108 if (((*psCCB->pui32WriteOffset + 1) & 255) !=
109 *psCCB->pui32ReadOffset) {
110 return &psCCB->psCommands[*psCCB->pui32WriteOffset];
113 END_LOOP_UNTIL_TIMEOUT();
118 enum PVRSRV_ERROR SGXScheduleCCBCommand(struct PVRSRV_SGXDEV_INFO *psDevInfo,
119 enum SGXMKIF_COMMAND_TYPE eCommandType,
120 struct SGXMKIF_COMMAND *psCommandData,
121 u32 ui32CallerID, u32 ui32PDumpFlags)
123 struct PVRSRV_SGX_CCB_INFO *psKernelCCB;
124 enum PVRSRV_ERROR eError = PVRSRV_OK;
125 struct SGXMKIF_COMMAND *psSGXCommand;
129 PVR_UNREFERENCED_PARAMETER(ui32CallerID);
130 PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
133 psKernelCCB = psDevInfo->psKernelCCBInfo;
135 psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
138 eError = PVRSRV_ERROR_TIMEOUT;
142 psCommandData->ui32Data[2] = psDevInfo->ui32CacheControl;
146 psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
149 psDevInfo->ui32CacheControl = 0;
151 *psSGXCommand = *psCommandData;
153 switch (eCommandType) {
154 case SGXMKIF_COMMAND_EDM_KICK:
155 psSGXCommand->ui32ServiceAddress =
156 psDevInfo->ui32HostKickAddress;
158 case SGXMKIF_COMMAND_REQUEST_SGXMISCINFO:
159 psSGXCommand->ui32ServiceAddress =
160 psDevInfo->ui32GetMiscInfoAddress;
162 case SGXMKIF_COMMAND_VIDEO_KICK:
164 PVR_DPF(PVR_DBG_ERROR,
165 "SGXScheduleCCBCommandKM: Unknown command type: %d",
167 eError = PVRSRV_ERROR_GENERIC;
172 if (ui32CallerID != ISR_ID) {
173 PDUMPCOMMENTWITHFLAGS(0,
174 "Poll for space in the Kernel CCB\r\n");
175 PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
176 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
177 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff, 0xff,
178 PDUMP_POLL_OPERATOR_NOTEQUAL,
179 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
181 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB command\r\n");
183 (void *)((u8 *)psKernelCCB->psCCBMemInfo->
185 (*psKernelCCB->pui32WriteOffset *
186 sizeof(struct SGXMKIF_COMMAND)));
188 PDUMPMEM(pvDumpCommand,
189 psKernelCCB->psCCBMemInfo,
190 psKernelCCB->ui32CCBDumpWOff *
191 sizeof(struct SGXMKIF_COMMAND),
192 sizeof(struct SGXMKIF_COMMAND), ui32PDumpFlags,
193 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
195 PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
196 psKernelCCB->psCCBMemInfo,
197 psKernelCCB->ui32CCBDumpWOff *
198 sizeof(struct SGXMKIF_COMMAND) +
199 offsetof(struct SGXMKIF_COMMAND, ui32Data[2]),
200 sizeof(u32), ui32PDumpFlags,
201 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
203 if (PDumpIsCaptureFrameKM() ||
204 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
205 psDevInfo->sPDContext.ui32CacheControl = 0;
208 *psKernelCCB->pui32WriteOffset =
209 (*psKernelCCB->pui32WriteOffset + 1) & 255;
212 if (ui32CallerID != ISR_ID) {
213 if (PDumpIsCaptureFrameKM() ||
214 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
215 psKernelCCB->ui32CCBDumpWOff =
216 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
218 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB write offset\r\n");
219 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
220 psKernelCCB->psCCBCtlMemInfo,
221 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
222 sizeof(u32), ui32PDumpFlags,
223 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
224 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB event kicker\r\n");
225 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
226 psDevInfo->psKernelCCBEventKickerMemInfo, 0,
227 sizeof(u32), ui32PDumpFlags,
228 MAKEUNIQUETAG(psDevInfo->
229 psKernelCCBEventKickerMemInfo));
230 PDUMPCOMMENTWITHFLAGS(0, "Event kick\r\n");
231 PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
232 EUR_CR_EVENT_KICK_NOW_MASK, 0);
235 *psDevInfo->pui32KernelCCBEventKicker =
236 (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
237 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
238 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
239 EUR_CR_EVENT_KICK_NOW_MASK);
241 #if defined(NO_HARDWARE)
243 *psKernelCCB->pui32ReadOffset =
244 (*psKernelCCB->pui32ReadOffset + 1) & 255;
251 enum PVRSRV_ERROR SGXScheduleCCBCommandKM(
252 struct PVRSRV_DEVICE_NODE *psDeviceNode,
253 enum SGXMKIF_COMMAND_TYPE eCommandType,
254 struct SGXMKIF_COMMAND *psCommandData,
255 u32 ui32CallerID, u32 ui32PDumpFlags)
257 enum PVRSRV_ERROR eError;
258 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
265 PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
266 PVRSRV_POWER_STATE_D0);
270 if (eError == PVRSRV_OK) {
271 psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
273 PVR_DPF(PVR_DBG_ERROR, "%s: can't power on device (%d)",
279 eError = SGXScheduleCCBCommand(psDevInfo, eCommandType, psCommandData,
280 ui32CallerID, ui32PDumpFlags);
282 if (ui32CallerID != ISR_ID)
283 SGXTestActivePowerEvent(psDeviceNode);
290 enum PVRSRV_ERROR SGXScheduleProcessQueues(struct PVRSRV_DEVICE_NODE
293 enum PVRSRV_ERROR eError;
294 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
295 struct SGXMKIF_HOST_CTL *psHostCtl =
296 psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
298 struct SGXMKIF_COMMAND sCommand = { 0 };
300 ui32PowerStatus = psHostCtl->ui32PowerStatus;
301 if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
305 PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
306 PVRSRV_POWER_STATE_D0);
307 if (eError != PVRSRV_OK)
310 sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
311 eError = SGXScheduleCCBCommand(psDeviceNode->pvDevice,
312 SGXMKIF_COMMAND_EDM_KICK, &sCommand,
314 if (eError != PVRSRV_OK) {
315 PVR_DPF(PVR_DBG_ERROR, "%s failed to schedule CCB command: %lu",
317 return PVRSRV_ERROR_GENERIC;
323 enum PVRSRV_ERROR SGXScheduleProcessQueuesKM(struct PVRSRV_DEVICE_NODE
326 enum PVRSRV_ERROR eError;
329 eError = SGXScheduleProcessQueues(psDeviceNode);
335 IMG_BOOL SGXIsDevicePowered(struct PVRSRV_DEVICE_NODE *psDeviceNode)
337 return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
340 enum PVRSRV_ERROR SGXGetInternalDevInfoKM(void *hDevCookie,
341 struct SGX_INTERNAL_DEVINFO
342 *psSGXInternalDevInfo)
344 struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
345 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
347 psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
348 psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
350 psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
351 (void *)psDevInfo->psKernelSGXHostCtlMemInfo;
356 #if defined(PDUMP) && !defined(EDM_USSE_HWDEBUG)
357 #define PDUMP_SGX_CLEANUP
360 void SGXCleanupRequest(struct PVRSRV_DEVICE_NODE *psDeviceNode,
361 struct IMG_DEV_VIRTADDR *psHWDataDevVAddr,
362 u32 ui32ResManRequestFlag)
364 struct PVRSRV_SGXDEV_INFO *psSGXDevInfo =
365 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
366 struct PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo =
367 psSGXDevInfo->psKernelSGXHostCtlMemInfo;
368 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
369 (struct SGXMKIF_HOST_CTL __iomem __force *)
370 psSGXHostCtlMemInfo->pvLinAddrKM;
371 #if defined(PDUMP_SGX_CLEANUP)
372 void *hUniqueTag = MAKEUNIQUETAG(psSGXHostCtlMemInfo);
377 if (readl(&psSGXHostCtl->ui32PowerStatus) &
378 PVRSRV_USSE_EDM_POWMAN_NO_WORK) {
381 if (psSGXDevInfo->ui32CacheControl &
382 SGX_BIF_INVALIDATE_PDCACHE) {
383 l = readl(&psSGXHostCtl->ui32ResManFlags);
384 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD;
385 writel(l, &psSGXHostCtl->ui32ResManFlags);
387 psSGXDevInfo->ui32CacheControl ^=
388 SGX_BIF_INVALIDATE_PDCACHE;
390 if (psSGXDevInfo->ui32CacheControl &
391 SGX_BIF_INVALIDATE_PTCACHE) {
392 l = readl(&psSGXHostCtl->ui32ResManFlags);
393 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT;
394 writel(l, &psSGXHostCtl->ui32ResManFlags);
396 psSGXDevInfo->ui32CacheControl ^=
397 SGX_BIF_INVALIDATE_PTCACHE;
400 if (psHWDataDevVAddr == NULL)
401 writel(0, &psSGXHostCtl->sResManCleanupData.uiAddr);
403 writel(psHWDataDevVAddr->uiAddr,
404 &psSGXHostCtl->sResManCleanupData.uiAddr);
406 l = readl(&psSGXHostCtl->ui32ResManFlags);
407 l |= ui32ResManRequestFlag;
408 writel(l, &psSGXHostCtl->ui32ResManFlags);
410 #if defined(PDUMP_SGX_CLEANUP)
412 PDUMPCOMMENTWITHFLAGS(0,
413 "TA/3D CCB Control - Request clean-up event on uKernel...");
414 PDUMPMEM(NULL, psSGXHostCtlMemInfo,
415 offsetof(struct SGXMKIF_HOST_CTL,
416 sResManCleanupData.uiAddr), sizeof(u32), 0,
418 PDUMPMEM(&ui32ResManRequestFlag, psSGXHostCtlMemInfo,
419 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
420 sizeof(u32), 0, hUniqueTag);
422 PDUMPCOMMENTWITHFLAGS(0, "Clean-up event on uKernel disabled");
425 SGXScheduleProcessQueues(psDeviceNode);
427 #if !defined(NO_HARDWARE)
428 if (PollForValueKM(&psSGXHostCtl->ui32ResManFlags,
429 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
430 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
431 MAX_HW_TIME_US / WAIT_TRY_COUNT,
432 WAIT_TRY_COUNT) != PVRSRV_OK) {
433 PVR_DPF(PVR_DBG_ERROR, "SGXCleanupRequest: "
434 "Wait for uKernel to clean up failed");
439 #if defined(PDUMP_SGX_CLEANUP)
441 PDUMPCOMMENTWITHFLAGS(0, "TA/3D CCB Control - "
442 "Wait for clean-up request to complete...");
443 PDUMPMEMPOL(psSGXHostCtlMemInfo,
444 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
445 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
446 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
447 PDUMP_POLL_OPERATOR_EQUAL, hUniqueTag);
450 l = readl(&psSGXHostCtl->ui32ResManFlags);
451 l &= ~ui32ResManRequestFlag;
452 writel(l, &psSGXHostCtl->ui32ResManFlags);
454 l = readl(&psSGXHostCtl->ui32ResManFlags);
455 l &= ~PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE;
456 writel(l, &psSGXHostCtl->ui32ResManFlags);
458 #if defined(PDUMP_SGX_CLEANUP)
459 PDUMPMEM(NULL, psSGXHostCtlMemInfo,
460 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
461 sizeof(u32), 0, hUniqueTag);
467 struct SGX_HW_RENDER_CONTEXT_CLEANUP {
468 struct PVRSRV_DEVICE_NODE *psDeviceNode;
469 struct IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
471 struct RESMAN_ITEM *psResItem;
474 static enum PVRSRV_ERROR SGXCleanupHWRenderContextCallback(void *pvParam,
477 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
479 PVR_UNREFERENCED_PARAMETER(ui32Param);
481 SGXCleanupRequest(psCleanup->psDeviceNode,
482 &psCleanup->sHWRenderContextDevVAddr,
483 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST);
485 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
486 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
487 psCleanup, psCleanup->hBlockAlloc);
492 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP {
493 struct PVRSRV_DEVICE_NODE *psDeviceNode;
494 struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
496 struct RESMAN_ITEM *psResItem;
499 static enum PVRSRV_ERROR SGXCleanupHWTransferContextCallback(void *pvParam,
502 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup =
503 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
505 PVR_UNREFERENCED_PARAMETER(ui32Param);
507 SGXCleanupRequest(psCleanup->psDeviceNode,
508 &psCleanup->sHWTransferContextDevVAddr,
509 PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST);
511 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
512 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
513 psCleanup, psCleanup->hBlockAlloc);
518 void *SGXRegisterHWRenderContextKM(void *psDeviceNode,
519 struct IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
520 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
522 enum PVRSRV_ERROR eError;
524 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
525 struct RESMAN_ITEM *psResItem;
527 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
528 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
529 (void **) &psCleanup, &hBlockAlloc);
531 if (eError != PVRSRV_OK) {
532 PVR_DPF(PVR_DBG_ERROR,
533 "SGXRegisterHWRenderContextKM: "
534 "Couldn't allocate memory for struct "
535 "SGX_HW_RENDER_CONTEXT_CLEANUP structure");
539 psCleanup->hBlockAlloc = hBlockAlloc;
540 psCleanup->psDeviceNode = psDeviceNode;
541 psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
543 psResItem = ResManRegisterRes(psPerProc->hResManContext,
544 RESMAN_TYPE_HW_RENDER_CONTEXT,
546 0, &SGXCleanupHWRenderContextCallback);
548 if (psResItem == NULL) {
549 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: "
550 "ResManRegisterRes failed");
551 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
552 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
553 psCleanup, psCleanup->hBlockAlloc);
558 psCleanup->psResItem = psResItem;
560 return (void *)psCleanup;
563 enum PVRSRV_ERROR SGXUnregisterHWRenderContextKM(void *hHWRenderContext)
565 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
567 PVR_ASSERT(hHWRenderContext != NULL);
569 psCleanup = (struct SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
571 if (psCleanup == NULL) {
572 PVR_DPF(PVR_DBG_ERROR,
573 "SGXUnregisterHWRenderContextKM: invalid parameter");
574 return PVRSRV_ERROR_INVALID_PARAMS;
577 ResManFreeResByPtr(psCleanup->psResItem);
582 void *SGXRegisterHWTransferContextKM(void *psDeviceNode,
583 struct IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
584 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
586 enum PVRSRV_ERROR eError;
588 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
589 struct RESMAN_ITEM *psResItem;
591 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
592 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
593 (void **) &psCleanup, &hBlockAlloc);
595 if (eError != PVRSRV_OK) {
596 PVR_DPF(PVR_DBG_ERROR,
597 "SGXRegisterHWTransferContextKM: "
598 "Couldn't allocate memory for struct "
599 "SGX_HW_TRANSFER_CONTEXT_CLEANUP structure");
603 psCleanup->hBlockAlloc = hBlockAlloc;
604 psCleanup->psDeviceNode = psDeviceNode;
605 psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
607 psResItem = ResManRegisterRes(psPerProc->hResManContext,
608 RESMAN_TYPE_HW_TRANSFER_CONTEXT,
610 0, &SGXCleanupHWTransferContextCallback);
612 if (psResItem == NULL) {
613 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: "
614 "ResManRegisterRes failed");
615 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
616 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
617 psCleanup, psCleanup->hBlockAlloc);
622 psCleanup->psResItem = psResItem;
624 return (void *)psCleanup;
627 enum PVRSRV_ERROR SGXUnregisterHWTransferContextKM(void *hHWTransferContext)
629 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
631 PVR_ASSERT(hHWTransferContext != NULL);
634 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
636 if (psCleanup == NULL) {
637 PVR_DPF(PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: "
638 "invalid parameter");
639 return PVRSRV_ERROR_INVALID_PARAMS;
642 ResManFreeResByPtr(psCleanup->psResItem);
647 static inline IMG_BOOL SGX2DQuerySyncOpsComplete(
648 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
649 u32 ui32ReadOpsPending, u32 ui32WriteOpsPending)
651 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
653 return (IMG_BOOL)((psSyncData->ui32ReadOpsComplete >=
654 ui32ReadOpsPending) &&
655 (psSyncData->ui32WriteOpsComplete >=
656 ui32WriteOpsPending));
659 enum PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(
660 struct PVRSRV_SGXDEV_INFO *psDevInfo,
661 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
662 IMG_BOOL bWaitForComplete)
664 u32 ui32ReadOpsPending, ui32WriteOpsPending;
666 PVR_UNREFERENCED_PARAMETER(psDevInfo);
668 PVR_DPF(PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start");
670 ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
671 ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
673 if (SGX2DQuerySyncOpsComplete
674 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
676 PVR_DPF(PVR_DBG_CALLTRACE,
677 "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.");
681 if (!bWaitForComplete) {
683 PVR_DPF(PVR_DBG_CALLTRACE,
684 "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.");
685 return PVRSRV_ERROR_CMD_NOT_PROCESSED;
688 PVR_DPF(PVR_DBG_MESSAGE,
689 "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.");
690 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
691 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
693 if (SGX2DQuerySyncOpsComplete
694 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
696 PVR_DPF(PVR_DBG_CALLTRACE,
697 "SGX2DQueryBlitsCompleteKM: "
698 "Wait over. Blits complete.");
702 END_LOOP_UNTIL_TIMEOUT();
704 PVR_DPF(PVR_DBG_ERROR,
705 "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.");
707 #if defined(CONFIG_PVR_DEBUG_EXTRA)
709 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
711 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
712 "Syncinfo: %p, Syncdata: %p",
713 psSyncInfo, psSyncData);
715 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
716 "Read ops complete: %d, Read ops pending: %d",
717 psSyncData->ui32ReadOpsComplete,
718 psSyncData->ui32ReadOpsPending);
719 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
720 "Write ops complete: %d, Write ops pending: %d",
721 psSyncData->ui32WriteOpsComplete,
722 psSyncData->ui32WriteOpsPending);
726 return PVRSRV_ERROR_TIMEOUT;
729 void SGXFlushHWRenderTargetKM(void *psDeviceNode,
730 struct IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
732 PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr);
734 SGXCleanupRequest((struct PVRSRV_DEVICE_NODE *)psDeviceNode,
735 &sHWRTDataSetDevVAddr,
736 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST);
739 u32 SGXConvertTimeStamp(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32TimeWraps,
745 ui64Clocks = ((u64) ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
746 (psDevInfo->ui32uKernelTimerClock -
747 (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
748 ui32Clocksx16 = (u32) (ui64Clocks / 16);
750 return ui32Clocksx16;