aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/pvr/sgxtransfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/pvr/sgxtransfer.c')
-rw-r--r--drivers/gpu/pvr/sgxtransfer.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/drivers/gpu/pvr/sgxtransfer.c b/drivers/gpu/pvr/sgxtransfer.c
new file mode 100644
index 00000000000..410b97ed629
--- /dev/null
+++ b/drivers/gpu/pvr/sgxtransfer.c
@@ -0,0 +1,293 @@
+/**********************************************************************
+ *
+ * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful but, except
+ * as otherwise stated in writing, without any warranty; without even the
+ * implied warranty of merchantability or fitness for a particular purpose.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ *
+ * Contact Information:
+ * Imagination Technologies Ltd. <gpl-support@imgtec.com>
+ * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ *
+ ******************************************************************************/
+
+
+#include <stddef.h>
+
+#include "sgxdefs.h"
+#include "services_headers.h"
+#include "buffer_manager.h"
+#include "sgxinfo.h"
+#include "sysconfig.h"
+#include "pdump_km.h"
+#include "mmu.h"
+#include "pvr_bridge.h"
+#include "sgx_bridge_km.h"
+#include "sgxinfokm.h"
+#include "osfunc.h"
+#include "pvr_debug.h"
+#include "sgxutils.h"
+
+enum PVRSRV_ERROR SGXSubmitTransferKM(void *hDevHandle,
+ struct PVRSRV_TRANSFER_SGX_KICK *psKick)
+{
+ struct PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo =
+ (struct PVRSRV_KERNEL_MEM_INFO *)psKick->hCCBMemInfo;
+ struct SGXMKIF_COMMAND sCommand = { 0 };
+ struct SGXMKIF_TRANSFERCMD_SHARED *psSharedTransferCmd;
+ struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+ enum PVRSRV_ERROR eError;
+
+ if (!CCB_OFFSET_IS_VALID
+ (struct SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick,
+ ui32SharedCmdCCBOffset)) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "SGXSubmitTransferKM: Invalid CCB offset");
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSharedTransferCmd =
+ CCB_DATA_FROM_OFFSET(struct SGXMKIF_TRANSFERCMD_SHARED,
+ psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
+
+ if (psKick->hTASyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->hTASyncInfo;
+
+ psSharedTransferCmd->ui32TASyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui32TASyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ } else {
+ psSharedTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if (psKick->h3DSyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->h3DSyncInfo;
+
+ psSharedTransferCmd->ui323DSyncWriteOpsPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psSharedTransferCmd->ui323DSyncReadOpsPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ } else {
+ psSharedTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+ psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+ }
+
+ if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL) {
+ if (psKick->ui32NumSrcSync > 0) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahSrcSyncInfo[0];
+
+ psSharedTransferCmd->ui32SrcWriteOpPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32SrcReadOpPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+ psSharedTransferCmd->sSrcWriteOpsCompleteDevAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sSrcReadOpsCompleteDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+ if (psKick->ui32NumDstSync > 0) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahDstSyncInfo[0];
+ psSharedTransferCmd->ui32DstWriteOpPendingVal =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSharedTransferCmd->ui32DstReadOpPendingVal =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSharedTransferCmd->sDstWriteOpsCompleteDevAddr =
+ psSyncInfo->sWriteOpsCompleteDevVAddr;
+ psSharedTransferCmd->sDstReadOpsCompleteDevAddr =
+ psSyncInfo->sReadOpsCompleteDevVAddr;
+ }
+
+ if (psKick->ui32NumSrcSync > 0) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+ psKick->ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+ }
+ if (psKick->ui32NumDstSync > 0) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+ }
+
+ if (psKick->ui32NumDstSync > 1 || psKick->ui32NumSrcSync > 1) {
+ PVR_DPF(PVR_DBG_ERROR,
+ "Transfer command doesn't support "
+ "more than 1 sync object per src/dst\ndst: %d, src: %d",
+ psKick->ui32NumDstSync, psKick->ui32NumSrcSync);
+ }
+#if defined(PDUMP)
+ if (PDumpIsCaptureFrameKM() ||
+ ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0)) {
+ PDUMPCOMMENT("Shared part of transfer command\r\n");
+ PDUMPMEM(psSharedTransferCmd,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff,
+ sizeof(struct SGXMKIF_TRANSFERCMD_SHARED),
+ psKick->ui32PDumpFlags, MAKEUNIQUETAG(psCCBMemInfo));
+
+ if ((psKick->ui32NumSrcSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+ PDUMPCOMMENT
+ ("Hack src surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32SrcWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT
+ ("Hack src surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32SrcReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+ if ((psKick->ui32NumDstSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo = psKick->ahDstSyncInfo[0];
+
+ PDUMPCOMMENT
+ ("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32DstWriteOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT
+ ("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff +
+ offsetof(struct SGXMKIF_TRANSFERCMD_SHARED,
+ ui32DstReadOpPendingVal),
+ sizeof(psSyncInfo->psSyncData->
+ ui32LastReadOpDumpVal),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
+ }
+
+ if ((psKick->ui32NumSrcSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahSrcSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+ }
+
+ if ((psKick->ui32NumDstSync > 0) &&
+ ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) ==
+ 0UL)) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[0];
+ psSyncInfo->psSyncData->ui32LastOpDumpVal++;
+ }
+ }
+#endif
+
+ sCommand.ui32Data[0] = PVRSRV_CCBFLAGS_TRANSFERCMD;
+ sCommand.ui32Data[1] = psKick->sHWTransferContextDevVAddr.uiAddr;
+
+ /* To aid in determining the next power down delay */
+ sgx_mark_new_command(hDevHandle);
+
+ eError = SGXScheduleCCBCommandKM(hDevHandle, SGXMKIF_COMMAND_EDM_KICK,
+ &sCommand, KERNEL_ID,
+ psKick->ui32PDumpFlags);
+
+#if defined(NO_HARDWARE)
+ if (!(psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE)) {
+ u32 i;
+
+ for (i = 0; i < psKick->ui32NumSrcSync; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahSrcSyncInfo[i];
+ psSyncInfo->psSyncData->ui32ReadOpsComplete =
+ psSyncInfo->psSyncData->ui32ReadOpsPending;
+ }
+
+ for (i = 0; i < psKick->ui32NumDstSync; i++) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ ahDstSyncInfo[i];
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+
+ }
+
+ if (psKick->hTASyncInfo != NULL) {
+ psSyncInfo =
+ (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ hTASyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+
+ if (psKick->h3DSyncInfo != NULL) {
+ psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+ h3DSyncInfo;
+
+ psSyncInfo->psSyncData->ui32WriteOpsComplete =
+ psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ }
+#endif
+
+ return eError;
+}
+