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"
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,
50 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
51 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
52 psDevInfo->psSGXHostCtl;
55 l = readl(&psSGXHostCtl->ui32NumActivePowerEvents);
57 writel(l, &psSGXHostCtl->ui32NumActivePowerEvents);
59 l = readl(&psSGXHostCtl->ui32PowerStatus);
60 if (l & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) {
61 if (ui32CallerID == ISR_ID)
62 psDeviceNode->bReProcessDeviceCommandComplete =
65 SGXScheduleProcessQueuesKM(psDeviceNode);
69 void SGXTestActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode,
72 enum PVRSRV_ERROR eError = PVRSRV_OK;
73 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
74 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl = psDevInfo->psSGXHostCtl;
77 l = readl(&psSGXHostCtl->ui32InterruptFlags);
78 if (!(l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER))
81 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
82 if (l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER)
85 /* Microkernel is idle and is requesting to be powered down. */
86 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
87 l |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
88 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
92 eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.
94 PVRSRV_POWER_STATE_D3,
95 ui32CallerID, IMG_FALSE);
96 if (eError == PVRSRV_OK)
97 SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
98 if (eError == PVRSRV_ERROR_RETRY) {
99 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
100 l &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
101 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
107 if (eError != PVRSRV_OK)
108 PVR_DPF(PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu",
112 static inline struct SGXMKIF_COMMAND *SGXAcquireKernelCCBSlot(
113 struct PVRSRV_SGX_CCB_INFO *psCCB)
115 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
116 if (((*psCCB->pui32WriteOffset + 1) & 255) !=
117 *psCCB->pui32ReadOffset) {
118 return &psCCB->psCommands[*psCCB->pui32WriteOffset];
121 END_LOOP_UNTIL_TIMEOUT();
126 enum PVRSRV_ERROR SGXScheduleCCBCommand(struct PVRSRV_SGXDEV_INFO *psDevInfo,
127 enum SGXMKIF_COMMAND_TYPE eCommandType,
128 struct SGXMKIF_COMMAND *psCommandData,
129 u32 ui32CallerID, u32 ui32PDumpFlags)
131 struct PVRSRV_SGX_CCB_INFO *psKernelCCB;
132 enum PVRSRV_ERROR eError = PVRSRV_OK;
133 struct SGXMKIF_COMMAND *psSGXCommand;
137 PVR_UNREFERENCED_PARAMETER(ui32CallerID);
138 PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
141 psKernelCCB = psDevInfo->psKernelCCBInfo;
143 psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
146 eError = PVRSRV_ERROR_TIMEOUT;
150 psCommandData->ui32Data[2] = psDevInfo->ui32CacheControl;
154 psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
157 psDevInfo->ui32CacheControl = 0;
159 *psSGXCommand = *psCommandData;
161 switch (eCommandType) {
162 case SGXMKIF_COMMAND_EDM_KICK:
163 psSGXCommand->ui32ServiceAddress =
164 psDevInfo->ui32HostKickAddress;
166 case SGXMKIF_COMMAND_REQUEST_SGXMISCINFO:
167 psSGXCommand->ui32ServiceAddress =
168 psDevInfo->ui32GetMiscInfoAddress;
170 case SGXMKIF_COMMAND_VIDEO_KICK:
172 PVR_DPF(PVR_DBG_ERROR,
173 "SGXScheduleCCBCommandKM: Unknown command type: %d",
175 eError = PVRSRV_ERROR_GENERIC;
180 if (ui32CallerID != ISR_ID) {
181 PDUMPCOMMENTWITHFLAGS(0,
182 "Poll for space in the Kernel CCB\r\n");
183 PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
184 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
185 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff, 0xff,
186 PDUMP_POLL_OPERATOR_NOTEQUAL, IMG_FALSE, IMG_FALSE,
187 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
189 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB command\r\n");
191 (void *)((u8 *)psKernelCCB->psCCBMemInfo->
193 (*psKernelCCB->pui32WriteOffset *
194 sizeof(struct SGXMKIF_COMMAND)));
196 PDUMPMEM(pvDumpCommand,
197 psKernelCCB->psCCBMemInfo,
198 psKernelCCB->ui32CCBDumpWOff *
199 sizeof(struct SGXMKIF_COMMAND),
200 sizeof(struct SGXMKIF_COMMAND), ui32PDumpFlags,
201 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
203 PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
204 psKernelCCB->psCCBMemInfo,
205 psKernelCCB->ui32CCBDumpWOff *
206 sizeof(struct SGXMKIF_COMMAND) +
207 offsetof(struct SGXMKIF_COMMAND, ui32Data[2]),
208 sizeof(u32), ui32PDumpFlags,
209 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
211 if (PDumpIsCaptureFrameKM() ||
212 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
213 psDevInfo->sPDContext.ui32CacheControl = 0;
216 *psKernelCCB->pui32WriteOffset =
217 (*psKernelCCB->pui32WriteOffset + 1) & 255;
220 if (ui32CallerID != ISR_ID) {
221 if (PDumpIsCaptureFrameKM() ||
222 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
223 psKernelCCB->ui32CCBDumpWOff =
224 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
226 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB write offset\r\n");
227 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
228 psKernelCCB->psCCBCtlMemInfo,
229 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
230 sizeof(u32), ui32PDumpFlags,
231 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
232 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB event kicker\r\n");
233 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
234 psDevInfo->psKernelCCBEventKickerMemInfo, 0,
235 sizeof(u32), ui32PDumpFlags,
236 MAKEUNIQUETAG(psDevInfo->
237 psKernelCCBEventKickerMemInfo));
238 PDUMPCOMMENTWITHFLAGS(0, "Event kick\r\n");
239 PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
240 EUR_CR_EVENT_KICK_NOW_MASK, 0);
243 *psDevInfo->pui32KernelCCBEventKicker =
244 (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
245 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
246 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
247 EUR_CR_EVENT_KICK_NOW_MASK);
249 #if defined(NO_HARDWARE)
251 *psKernelCCB->pui32ReadOffset =
252 (*psKernelCCB->pui32ReadOffset + 1) & 255;
259 enum PVRSRV_ERROR SGXScheduleCCBCommandKM(
260 struct PVRSRV_DEVICE_NODE *psDeviceNode,
261 enum SGXMKIF_COMMAND_TYPE eCommandType,
262 struct SGXMKIF_COMMAND *psCommandData,
263 u32 ui32CallerID, u32 ui32PDumpFlags)
265 enum PVRSRV_ERROR eError;
266 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
271 PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
272 PVRSRV_POWER_STATE_D0, ui32CallerID,
277 if (eError == PVRSRV_OK) {
278 psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
280 if (eError == PVRSRV_ERROR_RETRY) {
281 if (ui32CallerID == ISR_ID) {
282 psDeviceNode->bReProcessDeviceCommandComplete =
289 PVR_DPF(PVR_DBG_ERROR, "SGXScheduleCCBCommandKM "
290 "failed to acquire lock - "
291 "ui32CallerID:%ld eError:%lu",
292 ui32CallerID, eError);
296 eError = SGXScheduleCCBCommand(psDevInfo, eCommandType, psCommandData,
297 ui32CallerID, ui32PDumpFlags);
299 PVRSRVPowerUnlock(ui32CallerID);
301 if (ui32CallerID != ISR_ID)
302 SGXTestActivePowerEvent(psDeviceNode, ui32CallerID);
307 enum PVRSRV_ERROR SGXScheduleProcessQueuesKM(struct PVRSRV_DEVICE_NODE
310 enum PVRSRV_ERROR eError;
311 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
312 struct SGXMKIF_HOST_CTL *psHostCtl =
313 psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
315 struct SGXMKIF_COMMAND sCommand = { 0 };
317 ui32PowerStatus = psHostCtl->ui32PowerStatus;
318 if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
321 sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
323 SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_COMMAND_EDM_KICK,
324 &sCommand, ISR_ID, 0);
325 if (eError != PVRSRV_OK) {
326 PVR_DPF(PVR_DBG_ERROR, "SGXScheduleProcessQueuesKM failed "
327 "to schedule CCB command: %lu",
329 return PVRSRV_ERROR_GENERIC;
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);
376 if (readl(&psSGXHostCtl->ui32PowerStatus) &
377 PVRSRV_USSE_EDM_POWMAN_NO_WORK) {
380 if (psSGXDevInfo->ui32CacheControl &
381 SGX_BIF_INVALIDATE_PDCACHE) {
382 l = readl(&psSGXHostCtl->ui32ResManFlags);
383 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD;
384 writel(l, &psSGXHostCtl->ui32ResManFlags);
386 psSGXDevInfo->ui32CacheControl ^=
387 SGX_BIF_INVALIDATE_PDCACHE;
389 if (psSGXDevInfo->ui32CacheControl &
390 SGX_BIF_INVALIDATE_PTCACHE) {
391 l = readl(&psSGXHostCtl->ui32ResManFlags);
392 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT;
393 writel(l, &psSGXHostCtl->ui32ResManFlags);
395 psSGXDevInfo->ui32CacheControl ^=
396 SGX_BIF_INVALIDATE_PTCACHE;
399 if (psHWDataDevVAddr == NULL)
400 writel(0, &psSGXHostCtl->sResManCleanupData.uiAddr);
402 writel(psHWDataDevVAddr->uiAddr,
403 &psSGXHostCtl->sResManCleanupData.uiAddr);
405 l = readl(&psSGXHostCtl->ui32ResManFlags);
406 l |= ui32ResManRequestFlag;
407 writel(l, &psSGXHostCtl->ui32ResManFlags);
409 #if defined(PDUMP_SGX_CLEANUP)
411 PDUMPCOMMENTWITHFLAGS(0,
412 "TA/3D CCB Control - Request clean-up event on uKernel...");
413 PDUMPMEM(NULL, psSGXHostCtlMemInfo,
414 offsetof(struct SGXMKIF_HOST_CTL,
415 sResManCleanupData.uiAddr), sizeof(u32), 0,
417 PDUMPMEM(&ui32ResManRequestFlag, psSGXHostCtlMemInfo,
418 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
419 sizeof(u32), 0, hUniqueTag);
421 PDUMPCOMMENTWITHFLAGS(0, "Clean-up event on uKernel disabled");
424 SGXScheduleProcessQueuesKM(psDeviceNode);
426 #if !defined(NO_HARDWARE)
427 if (PollForValueKM(&psSGXHostCtl->ui32ResManFlags,
428 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
429 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
430 MAX_HW_TIME_US / WAIT_TRY_COUNT,
431 WAIT_TRY_COUNT) != PVRSRV_OK) {
432 PVR_DPF(PVR_DBG_ERROR, "SGXCleanupRequest: "
433 "Wait for uKernel to clean up failed");
438 #if defined(PDUMP_SGX_CLEANUP)
440 PDUMPCOMMENTWITHFLAGS(0, "TA/3D CCB Control - "
441 "Wait for clean-up request to complete...");
442 PDUMPMEMPOL(psSGXHostCtlMemInfo,
443 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
444 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
445 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
446 PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
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);
466 struct SGX_HW_RENDER_CONTEXT_CLEANUP {
467 struct PVRSRV_DEVICE_NODE *psDeviceNode;
468 struct IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
470 struct RESMAN_ITEM *psResItem;
473 static enum PVRSRV_ERROR SGXCleanupHWRenderContextCallback(void *pvParam,
476 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
478 PVR_UNREFERENCED_PARAMETER(ui32Param);
480 SGXCleanupRequest(psCleanup->psDeviceNode,
481 &psCleanup->sHWRenderContextDevVAddr,
482 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST);
484 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
485 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
486 psCleanup, psCleanup->hBlockAlloc);
491 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP {
492 struct PVRSRV_DEVICE_NODE *psDeviceNode;
493 struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
495 struct RESMAN_ITEM *psResItem;
498 static enum PVRSRV_ERROR SGXCleanupHWTransferContextCallback(void *pvParam,
501 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup =
502 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
504 PVR_UNREFERENCED_PARAMETER(ui32Param);
506 SGXCleanupRequest(psCleanup->psDeviceNode,
507 &psCleanup->sHWTransferContextDevVAddr,
508 PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST);
510 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
511 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
512 psCleanup, psCleanup->hBlockAlloc);
517 void *SGXRegisterHWRenderContextKM(void *psDeviceNode,
518 struct IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
519 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
521 enum PVRSRV_ERROR eError;
523 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
524 struct RESMAN_ITEM *psResItem;
526 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
527 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
528 (void **) &psCleanup, &hBlockAlloc);
530 if (eError != PVRSRV_OK) {
531 PVR_DPF(PVR_DBG_ERROR,
532 "SGXRegisterHWRenderContextKM: "
533 "Couldn't allocate memory for struct "
534 "SGX_HW_RENDER_CONTEXT_CLEANUP structure");
538 psCleanup->hBlockAlloc = hBlockAlloc;
539 psCleanup->psDeviceNode = psDeviceNode;
540 psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
542 psResItem = ResManRegisterRes(psPerProc->hResManContext,
543 RESMAN_TYPE_HW_RENDER_CONTEXT,
545 0, &SGXCleanupHWRenderContextCallback);
547 if (psResItem == NULL) {
548 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: "
549 "ResManRegisterRes failed");
550 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
551 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
552 psCleanup, psCleanup->hBlockAlloc);
557 psCleanup->psResItem = psResItem;
559 return (void *)psCleanup;
562 enum PVRSRV_ERROR SGXUnregisterHWRenderContextKM(void *hHWRenderContext)
564 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
566 PVR_ASSERT(hHWRenderContext != NULL);
568 psCleanup = (struct SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
570 if (psCleanup == NULL) {
571 PVR_DPF(PVR_DBG_ERROR,
572 "SGXUnregisterHWRenderContextKM: invalid parameter");
573 return PVRSRV_ERROR_INVALID_PARAMS;
576 ResManFreeResByPtr(psCleanup->psResItem);
581 void *SGXRegisterHWTransferContextKM(void *psDeviceNode,
582 struct IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
583 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
585 enum PVRSRV_ERROR eError;
587 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
588 struct RESMAN_ITEM *psResItem;
590 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
591 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
592 (void **) &psCleanup, &hBlockAlloc);
594 if (eError != PVRSRV_OK) {
595 PVR_DPF(PVR_DBG_ERROR,
596 "SGXRegisterHWTransferContextKM: "
597 "Couldn't allocate memory for struct "
598 "SGX_HW_TRANSFER_CONTEXT_CLEANUP structure");
602 psCleanup->hBlockAlloc = hBlockAlloc;
603 psCleanup->psDeviceNode = psDeviceNode;
604 psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
606 psResItem = ResManRegisterRes(psPerProc->hResManContext,
607 RESMAN_TYPE_HW_TRANSFER_CONTEXT,
609 0, &SGXCleanupHWTransferContextCallback);
611 if (psResItem == NULL) {
612 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: "
613 "ResManRegisterRes failed");
614 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
615 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
616 psCleanup, psCleanup->hBlockAlloc);
621 psCleanup->psResItem = psResItem;
623 return (void *)psCleanup;
626 enum PVRSRV_ERROR SGXUnregisterHWTransferContextKM(void *hHWTransferContext)
628 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
630 PVR_ASSERT(hHWTransferContext != NULL);
633 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
635 if (psCleanup == NULL) {
636 PVR_DPF(PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: "
637 "invalid parameter");
638 return PVRSRV_ERROR_INVALID_PARAMS;
641 ResManFreeResByPtr(psCleanup->psResItem);
646 static inline IMG_BOOL SGX2DQuerySyncOpsComplete(
647 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
648 u32 ui32ReadOpsPending, u32 ui32WriteOpsPending)
650 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
652 return (IMG_BOOL)((psSyncData->ui32ReadOpsComplete >=
653 ui32ReadOpsPending) &&
654 (psSyncData->ui32WriteOpsComplete >=
655 ui32WriteOpsPending));
658 enum PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(
659 struct PVRSRV_SGXDEV_INFO *psDevInfo,
660 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
661 IMG_BOOL bWaitForComplete)
663 u32 ui32ReadOpsPending, ui32WriteOpsPending;
665 PVR_UNREFERENCED_PARAMETER(psDevInfo);
667 PVR_DPF(PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start");
669 ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
670 ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
672 if (SGX2DQuerySyncOpsComplete
673 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
675 PVR_DPF(PVR_DBG_CALLTRACE,
676 "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.");
680 if (!bWaitForComplete) {
682 PVR_DPF(PVR_DBG_CALLTRACE,
683 "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.");
684 return PVRSRV_ERROR_CMD_NOT_PROCESSED;
687 PVR_DPF(PVR_DBG_MESSAGE,
688 "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.");
689 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
690 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
692 if (SGX2DQuerySyncOpsComplete
693 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
695 PVR_DPF(PVR_DBG_CALLTRACE,
696 "SGX2DQueryBlitsCompleteKM: "
697 "Wait over. Blits complete.");
701 END_LOOP_UNTIL_TIMEOUT();
703 PVR_DPF(PVR_DBG_ERROR,
704 "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.");
706 #if defined(CONFIG_PVR_DEBUG_EXTRA)
708 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
710 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
711 "Syncinfo: %p, Syncdata: %p",
712 psSyncInfo, psSyncData);
714 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
715 "Read ops complete: %d, Read ops pending: %d",
716 psSyncData->ui32ReadOpsComplete,
717 psSyncData->ui32ReadOpsPending);
718 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
719 "Write ops complete: %d, Write ops pending: %d",
720 psSyncData->ui32WriteOpsComplete,
721 psSyncData->ui32WriteOpsPending);
725 return PVRSRV_ERROR_TIMEOUT;
728 void SGXFlushHWRenderTargetKM(void *psDeviceNode,
729 struct IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
731 PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr);
733 SGXCleanupRequest((struct PVRSRV_DEVICE_NODE *)psDeviceNode,
734 &sHWRTDataSetDevVAddr,
735 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST);
738 u32 SGXConvertTimeStamp(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32TimeWraps,
744 ui64Clocks = ((u64) ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
745 (psDevInfo->ui32uKernelTimerClock -
746 (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
747 ui32Clocksx16 = (u32) (ui64Clocks / 16);
749 return ui32Clocksx16;