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)
49 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
50 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
51 psDevInfo->psSGXHostCtl;
54 l = readl(&psSGXHostCtl->ui32NumActivePowerEvents);
56 writel(l, &psSGXHostCtl->ui32NumActivePowerEvents);
58 l = readl(&psSGXHostCtl->ui32PowerStatus);
59 if (l & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE)
60 SGXScheduleProcessQueues(psDeviceNode);
63 void SGXTestActivePowerEvent(struct PVRSRV_DEVICE_NODE *psDeviceNode)
65 enum PVRSRV_ERROR eError = PVRSRV_OK;
66 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
67 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl = psDevInfo->psSGXHostCtl;
70 l = readl(&psSGXHostCtl->ui32InterruptFlags);
71 if (!(l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER))
74 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
75 if (l & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER)
78 /* Microkernel is idle and is requesting to be powered down. */
79 l = readl(&psSGXHostCtl->ui32InterruptClearFlags);
80 l |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
81 writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
85 eError = PVRSRVSetDevicePowerStateKM(
86 psDeviceNode->sDevId.ui32DeviceIndex,
87 PVRSRV_POWER_STATE_D3);
88 if (eError == PVRSRV_OK)
89 SGXPostActivePowerEvent(psDeviceNode);
93 if (eError != PVRSRV_OK)
94 PVR_DPF(PVR_DBG_ERROR, "SGXTestActivePowerEvent error:%lu",
98 static inline struct SGXMKIF_COMMAND *SGXAcquireKernelCCBSlot(
99 struct PVRSRV_SGX_CCB_INFO *psCCB)
101 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
102 if (((*psCCB->pui32WriteOffset + 1) & 255) !=
103 *psCCB->pui32ReadOffset) {
104 return &psCCB->psCommands[*psCCB->pui32WriteOffset];
107 END_LOOP_UNTIL_TIMEOUT();
112 enum PVRSRV_ERROR SGXScheduleCCBCommand(struct PVRSRV_SGXDEV_INFO *psDevInfo,
113 enum SGXMKIF_COMMAND_TYPE eCommandType,
114 struct SGXMKIF_COMMAND *psCommandData,
115 u32 ui32CallerID, u32 ui32PDumpFlags)
117 struct PVRSRV_SGX_CCB_INFO *psKernelCCB;
118 enum PVRSRV_ERROR eError = PVRSRV_OK;
119 struct SGXMKIF_COMMAND *psSGXCommand;
123 PVR_UNREFERENCED_PARAMETER(ui32CallerID);
124 PVR_UNREFERENCED_PARAMETER(ui32PDumpFlags);
127 psKernelCCB = psDevInfo->psKernelCCBInfo;
129 psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
132 eError = PVRSRV_ERROR_TIMEOUT;
136 psCommandData->ui32Data[2] = psDevInfo->ui32CacheControl;
140 psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
143 psDevInfo->ui32CacheControl = 0;
145 *psSGXCommand = *psCommandData;
147 switch (eCommandType) {
148 case SGXMKIF_COMMAND_EDM_KICK:
149 psSGXCommand->ui32ServiceAddress =
150 psDevInfo->ui32HostKickAddress;
152 case SGXMKIF_COMMAND_REQUEST_SGXMISCINFO:
153 psSGXCommand->ui32ServiceAddress =
154 psDevInfo->ui32GetMiscInfoAddress;
156 case SGXMKIF_COMMAND_VIDEO_KICK:
158 PVR_DPF(PVR_DBG_ERROR,
159 "SGXScheduleCCBCommandKM: Unknown command type: %d",
161 eError = PVRSRV_ERROR_GENERIC;
166 if (ui32CallerID != ISR_ID) {
167 PDUMPCOMMENTWITHFLAGS(0,
168 "Poll for space in the Kernel CCB\r\n");
169 PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
170 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
171 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xff, 0xff,
172 PDUMP_POLL_OPERATOR_NOTEQUAL, IMG_FALSE, IMG_FALSE,
173 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
175 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB command\r\n");
177 (void *)((u8 *)psKernelCCB->psCCBMemInfo->
179 (*psKernelCCB->pui32WriteOffset *
180 sizeof(struct SGXMKIF_COMMAND)));
182 PDUMPMEM(pvDumpCommand,
183 psKernelCCB->psCCBMemInfo,
184 psKernelCCB->ui32CCBDumpWOff *
185 sizeof(struct SGXMKIF_COMMAND),
186 sizeof(struct SGXMKIF_COMMAND), ui32PDumpFlags,
187 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
189 PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
190 psKernelCCB->psCCBMemInfo,
191 psKernelCCB->ui32CCBDumpWOff *
192 sizeof(struct SGXMKIF_COMMAND) +
193 offsetof(struct SGXMKIF_COMMAND, ui32Data[2]),
194 sizeof(u32), ui32PDumpFlags,
195 MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
197 if (PDumpIsCaptureFrameKM() ||
198 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
199 psDevInfo->sPDContext.ui32CacheControl = 0;
202 *psKernelCCB->pui32WriteOffset =
203 (*psKernelCCB->pui32WriteOffset + 1) & 255;
206 if (ui32CallerID != ISR_ID) {
207 if (PDumpIsCaptureFrameKM() ||
208 ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
209 psKernelCCB->ui32CCBDumpWOff =
210 (psKernelCCB->ui32CCBDumpWOff + 1) & 0xFF;
212 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB write offset\r\n");
213 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
214 psKernelCCB->psCCBCtlMemInfo,
215 offsetof(struct PVRSRV_SGX_CCB_CTL, ui32WriteOffset),
216 sizeof(u32), ui32PDumpFlags,
217 MAKEUNIQUETAG(psKernelCCB->psCCBCtlMemInfo));
218 PDUMPCOMMENTWITHFLAGS(0, "Kernel CCB event kicker\r\n");
219 PDUMPMEM(&psKernelCCB->ui32CCBDumpWOff,
220 psDevInfo->psKernelCCBEventKickerMemInfo, 0,
221 sizeof(u32), ui32PDumpFlags,
222 MAKEUNIQUETAG(psDevInfo->
223 psKernelCCBEventKickerMemInfo));
224 PDUMPCOMMENTWITHFLAGS(0, "Event kick\r\n");
225 PDUMPREGWITHFLAGS(SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
226 EUR_CR_EVENT_KICK_NOW_MASK, 0);
229 *psDevInfo->pui32KernelCCBEventKicker =
230 (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
231 OSWriteHWReg(psDevInfo->pvRegsBaseKM,
232 SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
233 EUR_CR_EVENT_KICK_NOW_MASK);
235 #if defined(NO_HARDWARE)
237 *psKernelCCB->pui32ReadOffset =
238 (*psKernelCCB->pui32ReadOffset + 1) & 255;
245 enum PVRSRV_ERROR SGXScheduleCCBCommandKM(
246 struct PVRSRV_DEVICE_NODE *psDeviceNode,
247 enum SGXMKIF_COMMAND_TYPE eCommandType,
248 struct SGXMKIF_COMMAND *psCommandData,
249 u32 ui32CallerID, u32 ui32PDumpFlags)
251 enum PVRSRV_ERROR eError;
252 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
259 PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
260 PVRSRV_POWER_STATE_D0);
264 if (eError == PVRSRV_OK) {
265 psDeviceNode->bReProcessDeviceCommandComplete = IMG_FALSE;
267 PVR_DPF(PVR_DBG_ERROR, "%s: can't power on device (%d)",
273 eError = SGXScheduleCCBCommand(psDevInfo, eCommandType, psCommandData,
274 ui32CallerID, ui32PDumpFlags);
276 if (ui32CallerID != ISR_ID)
277 SGXTestActivePowerEvent(psDeviceNode);
284 enum PVRSRV_ERROR SGXScheduleProcessQueues(struct PVRSRV_DEVICE_NODE
287 enum PVRSRV_ERROR eError;
288 struct PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
289 struct SGXMKIF_HOST_CTL *psHostCtl =
290 psDevInfo->psKernelSGXHostCtlMemInfo->pvLinAddrKM;
292 struct SGXMKIF_COMMAND sCommand = { 0 };
294 ui32PowerStatus = psHostCtl->ui32PowerStatus;
295 if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
299 PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
300 PVRSRV_POWER_STATE_D0);
301 if (eError != PVRSRV_OK)
304 sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_PROCESS_QUEUESCMD;
305 eError = SGXScheduleCCBCommand(psDeviceNode->pvDevice,
306 SGXMKIF_COMMAND_EDM_KICK, &sCommand,
308 if (eError != PVRSRV_OK) {
309 PVR_DPF(PVR_DBG_ERROR, "%s failed to schedule CCB command: %lu",
311 return PVRSRV_ERROR_GENERIC;
317 enum PVRSRV_ERROR SGXScheduleProcessQueuesKM(struct PVRSRV_DEVICE_NODE
320 enum PVRSRV_ERROR eError;
323 eError = SGXScheduleProcessQueues(psDeviceNode);
329 IMG_BOOL SGXIsDevicePowered(struct PVRSRV_DEVICE_NODE *psDeviceNode)
331 return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
334 enum PVRSRV_ERROR SGXGetInternalDevInfoKM(void *hDevCookie,
335 struct SGX_INTERNAL_DEVINFO
336 *psSGXInternalDevInfo)
338 struct PVRSRV_SGXDEV_INFO *psDevInfo = (struct PVRSRV_SGXDEV_INFO *)
339 ((struct PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
341 psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
342 psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
344 psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
345 (void *)psDevInfo->psKernelSGXHostCtlMemInfo;
350 #if defined(PDUMP) && !defined(EDM_USSE_HWDEBUG)
351 #define PDUMP_SGX_CLEANUP
354 void SGXCleanupRequest(struct PVRSRV_DEVICE_NODE *psDeviceNode,
355 struct IMG_DEV_VIRTADDR *psHWDataDevVAddr,
356 u32 ui32ResManRequestFlag)
358 struct PVRSRV_SGXDEV_INFO *psSGXDevInfo =
359 (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
360 struct PVRSRV_KERNEL_MEM_INFO *psSGXHostCtlMemInfo =
361 psSGXDevInfo->psKernelSGXHostCtlMemInfo;
362 struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
363 (struct SGXMKIF_HOST_CTL __iomem __force *)
364 psSGXHostCtlMemInfo->pvLinAddrKM;
365 #if defined(PDUMP_SGX_CLEANUP)
366 void *hUniqueTag = MAKEUNIQUETAG(psSGXHostCtlMemInfo);
371 if (readl(&psSGXHostCtl->ui32PowerStatus) &
372 PVRSRV_USSE_EDM_POWMAN_NO_WORK) {
375 if (psSGXDevInfo->ui32CacheControl &
376 SGX_BIF_INVALIDATE_PDCACHE) {
377 l = readl(&psSGXHostCtl->ui32ResManFlags);
378 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPD;
379 writel(l, &psSGXHostCtl->ui32ResManFlags);
381 psSGXDevInfo->ui32CacheControl ^=
382 SGX_BIF_INVALIDATE_PDCACHE;
384 if (psSGXDevInfo->ui32CacheControl &
385 SGX_BIF_INVALIDATE_PTCACHE) {
386 l = readl(&psSGXHostCtl->ui32ResManFlags);
387 l |= PVRSRV_USSE_EDM_RESMAN_CLEANUP_INVALPT;
388 writel(l, &psSGXHostCtl->ui32ResManFlags);
390 psSGXDevInfo->ui32CacheControl ^=
391 SGX_BIF_INVALIDATE_PTCACHE;
394 if (psHWDataDevVAddr == NULL)
395 writel(0, &psSGXHostCtl->sResManCleanupData.uiAddr);
397 writel(psHWDataDevVAddr->uiAddr,
398 &psSGXHostCtl->sResManCleanupData.uiAddr);
400 l = readl(&psSGXHostCtl->ui32ResManFlags);
401 l |= ui32ResManRequestFlag;
402 writel(l, &psSGXHostCtl->ui32ResManFlags);
404 #if defined(PDUMP_SGX_CLEANUP)
406 PDUMPCOMMENTWITHFLAGS(0,
407 "TA/3D CCB Control - Request clean-up event on uKernel...");
408 PDUMPMEM(NULL, psSGXHostCtlMemInfo,
409 offsetof(struct SGXMKIF_HOST_CTL,
410 sResManCleanupData.uiAddr), sizeof(u32), 0,
412 PDUMPMEM(&ui32ResManRequestFlag, psSGXHostCtlMemInfo,
413 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
414 sizeof(u32), 0, hUniqueTag);
416 PDUMPCOMMENTWITHFLAGS(0, "Clean-up event on uKernel disabled");
419 SGXScheduleProcessQueues(psDeviceNode);
421 #if !defined(NO_HARDWARE)
422 if (PollForValueKM(&psSGXHostCtl->ui32ResManFlags,
423 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
424 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
425 MAX_HW_TIME_US / WAIT_TRY_COUNT,
426 WAIT_TRY_COUNT) != PVRSRV_OK) {
427 PVR_DPF(PVR_DBG_ERROR, "SGXCleanupRequest: "
428 "Wait for uKernel to clean up failed");
433 #if defined(PDUMP_SGX_CLEANUP)
435 PDUMPCOMMENTWITHFLAGS(0, "TA/3D CCB Control - "
436 "Wait for clean-up request to complete...");
437 PDUMPMEMPOL(psSGXHostCtlMemInfo,
438 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
439 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
440 PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE,
441 PDUMP_POLL_OPERATOR_EQUAL, IMG_FALSE, IMG_FALSE,
445 l = readl(&psSGXHostCtl->ui32ResManFlags);
446 l &= ~ui32ResManRequestFlag;
447 writel(l, &psSGXHostCtl->ui32ResManFlags);
449 l = readl(&psSGXHostCtl->ui32ResManFlags);
450 l &= ~PVRSRV_USSE_EDM_RESMAN_CLEANUP_COMPLETE;
451 writel(l, &psSGXHostCtl->ui32ResManFlags);
453 #if defined(PDUMP_SGX_CLEANUP)
454 PDUMPMEM(NULL, psSGXHostCtlMemInfo,
455 offsetof(struct SGXMKIF_HOST_CTL, ui32ResManFlags),
456 sizeof(u32), 0, hUniqueTag);
462 struct SGX_HW_RENDER_CONTEXT_CLEANUP {
463 struct PVRSRV_DEVICE_NODE *psDeviceNode;
464 struct IMG_DEV_VIRTADDR sHWRenderContextDevVAddr;
466 struct RESMAN_ITEM *psResItem;
469 static enum PVRSRV_ERROR SGXCleanupHWRenderContextCallback(void *pvParam,
472 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup = pvParam;
474 PVR_UNREFERENCED_PARAMETER(ui32Param);
476 SGXCleanupRequest(psCleanup->psDeviceNode,
477 &psCleanup->sHWRenderContextDevVAddr,
478 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RC_REQUEST);
480 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
481 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
482 psCleanup, psCleanup->hBlockAlloc);
487 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP {
488 struct PVRSRV_DEVICE_NODE *psDeviceNode;
489 struct IMG_DEV_VIRTADDR sHWTransferContextDevVAddr;
491 struct RESMAN_ITEM *psResItem;
494 static enum PVRSRV_ERROR SGXCleanupHWTransferContextCallback(void *pvParam,
497 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup =
498 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)pvParam;
500 PVR_UNREFERENCED_PARAMETER(ui32Param);
502 SGXCleanupRequest(psCleanup->psDeviceNode,
503 &psCleanup->sHWTransferContextDevVAddr,
504 PVRSRV_USSE_EDM_RESMAN_CLEANUP_TC_REQUEST);
506 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
507 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
508 psCleanup, psCleanup->hBlockAlloc);
513 void *SGXRegisterHWRenderContextKM(void *psDeviceNode,
514 struct IMG_DEV_VIRTADDR *psHWRenderContextDevVAddr,
515 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
517 enum PVRSRV_ERROR eError;
519 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
520 struct RESMAN_ITEM *psResItem;
522 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
523 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
524 (void **) &psCleanup, &hBlockAlloc);
526 if (eError != PVRSRV_OK) {
527 PVR_DPF(PVR_DBG_ERROR,
528 "SGXRegisterHWRenderContextKM: "
529 "Couldn't allocate memory for struct "
530 "SGX_HW_RENDER_CONTEXT_CLEANUP structure");
534 psCleanup->hBlockAlloc = hBlockAlloc;
535 psCleanup->psDeviceNode = psDeviceNode;
536 psCleanup->sHWRenderContextDevVAddr = *psHWRenderContextDevVAddr;
538 psResItem = ResManRegisterRes(psPerProc->hResManContext,
539 RESMAN_TYPE_HW_RENDER_CONTEXT,
541 0, &SGXCleanupHWRenderContextCallback);
543 if (psResItem == NULL) {
544 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWRenderContextKM: "
545 "ResManRegisterRes failed");
546 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
547 sizeof(struct SGX_HW_RENDER_CONTEXT_CLEANUP),
548 psCleanup, psCleanup->hBlockAlloc);
553 psCleanup->psResItem = psResItem;
555 return (void *)psCleanup;
558 enum PVRSRV_ERROR SGXUnregisterHWRenderContextKM(void *hHWRenderContext)
560 struct SGX_HW_RENDER_CONTEXT_CLEANUP *psCleanup;
562 PVR_ASSERT(hHWRenderContext != NULL);
564 psCleanup = (struct SGX_HW_RENDER_CONTEXT_CLEANUP *)hHWRenderContext;
566 if (psCleanup == NULL) {
567 PVR_DPF(PVR_DBG_ERROR,
568 "SGXUnregisterHWRenderContextKM: invalid parameter");
569 return PVRSRV_ERROR_INVALID_PARAMS;
572 ResManFreeResByPtr(psCleanup->psResItem);
577 void *SGXRegisterHWTransferContextKM(void *psDeviceNode,
578 struct IMG_DEV_VIRTADDR *psHWTransferContextDevVAddr,
579 struct PVRSRV_PER_PROCESS_DATA *psPerProc)
581 enum PVRSRV_ERROR eError;
583 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
584 struct RESMAN_ITEM *psResItem;
586 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
587 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
588 (void **) &psCleanup, &hBlockAlloc);
590 if (eError != PVRSRV_OK) {
591 PVR_DPF(PVR_DBG_ERROR,
592 "SGXRegisterHWTransferContextKM: "
593 "Couldn't allocate memory for struct "
594 "SGX_HW_TRANSFER_CONTEXT_CLEANUP structure");
598 psCleanup->hBlockAlloc = hBlockAlloc;
599 psCleanup->psDeviceNode = psDeviceNode;
600 psCleanup->sHWTransferContextDevVAddr = *psHWTransferContextDevVAddr;
602 psResItem = ResManRegisterRes(psPerProc->hResManContext,
603 RESMAN_TYPE_HW_TRANSFER_CONTEXT,
605 0, &SGXCleanupHWTransferContextCallback);
607 if (psResItem == NULL) {
608 PVR_DPF(PVR_DBG_ERROR, "SGXRegisterHWTransferContextKM: "
609 "ResManRegisterRes failed");
610 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
611 sizeof(struct SGX_HW_TRANSFER_CONTEXT_CLEANUP),
612 psCleanup, psCleanup->hBlockAlloc);
617 psCleanup->psResItem = psResItem;
619 return (void *)psCleanup;
622 enum PVRSRV_ERROR SGXUnregisterHWTransferContextKM(void *hHWTransferContext)
624 struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *psCleanup;
626 PVR_ASSERT(hHWTransferContext != NULL);
629 (struct SGX_HW_TRANSFER_CONTEXT_CLEANUP *)hHWTransferContext;
631 if (psCleanup == NULL) {
632 PVR_DPF(PVR_DBG_ERROR, "SGXUnregisterHWTransferContextKM: "
633 "invalid parameter");
634 return PVRSRV_ERROR_INVALID_PARAMS;
637 ResManFreeResByPtr(psCleanup->psResItem);
642 static inline IMG_BOOL SGX2DQuerySyncOpsComplete(
643 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
644 u32 ui32ReadOpsPending, u32 ui32WriteOpsPending)
646 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
648 return (IMG_BOOL)((psSyncData->ui32ReadOpsComplete >=
649 ui32ReadOpsPending) &&
650 (psSyncData->ui32WriteOpsComplete >=
651 ui32WriteOpsPending));
654 enum PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(
655 struct PVRSRV_SGXDEV_INFO *psDevInfo,
656 struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
657 IMG_BOOL bWaitForComplete)
659 u32 ui32ReadOpsPending, ui32WriteOpsPending;
661 PVR_UNREFERENCED_PARAMETER(psDevInfo);
663 PVR_DPF(PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Start");
665 ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOpsPending;
666 ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
668 if (SGX2DQuerySyncOpsComplete
669 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
671 PVR_DPF(PVR_DBG_CALLTRACE,
672 "SGX2DQueryBlitsCompleteKM: No wait. Blits complete.");
676 if (!bWaitForComplete) {
678 PVR_DPF(PVR_DBG_CALLTRACE,
679 "SGX2DQueryBlitsCompleteKM: No wait. Ops pending.");
680 return PVRSRV_ERROR_CMD_NOT_PROCESSED;
683 PVR_DPF(PVR_DBG_MESSAGE,
684 "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling.");
685 LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US) {
686 OSWaitus(MAX_HW_TIME_US / WAIT_TRY_COUNT);
688 if (SGX2DQuerySyncOpsComplete
689 (psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending)) {
691 PVR_DPF(PVR_DBG_CALLTRACE,
692 "SGX2DQueryBlitsCompleteKM: "
693 "Wait over. Blits complete.");
697 END_LOOP_UNTIL_TIMEOUT();
699 PVR_DPF(PVR_DBG_ERROR,
700 "SGX2DQueryBlitsCompleteKM: Timed out. Ops pending.");
702 #if defined(CONFIG_PVR_DEBUG_EXTRA)
704 struct PVRSRV_SYNC_DATA *psSyncData = psSyncInfo->psSyncData;
706 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
707 "Syncinfo: %p, Syncdata: %p",
708 psSyncInfo, psSyncData);
710 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
711 "Read ops complete: %d, Read ops pending: %d",
712 psSyncData->ui32ReadOpsComplete,
713 psSyncData->ui32ReadOpsPending);
714 PVR_TRACE("SGX2DQueryBlitsCompleteKM: "
715 "Write ops complete: %d, Write ops pending: %d",
716 psSyncData->ui32WriteOpsComplete,
717 psSyncData->ui32WriteOpsPending);
721 return PVRSRV_ERROR_TIMEOUT;
724 void SGXFlushHWRenderTargetKM(void *psDeviceNode,
725 struct IMG_DEV_VIRTADDR sHWRTDataSetDevVAddr)
727 PVR_ASSERT(sHWRTDataSetDevVAddr.uiAddr);
729 SGXCleanupRequest((struct PVRSRV_DEVICE_NODE *)psDeviceNode,
730 &sHWRTDataSetDevVAddr,
731 PVRSRV_USSE_EDM_RESMAN_CLEANUP_RT_REQUEST);
734 u32 SGXConvertTimeStamp(struct PVRSRV_SGXDEV_INFO *psDevInfo, u32 ui32TimeWraps,
740 ui64Clocks = ((u64) ui32TimeWraps * psDevInfo->ui32uKernelTimerClock) +
741 (psDevInfo->ui32uKernelTimerClock -
742 (ui32Time & EUR_CR_EVENT_TIMER_VALUE_MASK));
743 ui32Clocksx16 = (u32) (ui64Clocks / 16);
745 return ui32Clocksx16;