Maemo patchset 20101501+0m5
[h-e-n] / drivers / gpu / pvr / sgxtransfer.c
diff --git a/drivers/gpu/pvr/sgxtransfer.c b/drivers/gpu/pvr/sgxtransfer.c
new file mode 100644 (file)
index 0000000..0cc3a0d
--- /dev/null
@@ -0,0 +1,265 @@
+/**********************************************************************
+ *
+ * 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 PVRSRV_SGX_COMMAND sCommand = { 0 };
+       struct PVR3DIF4_TRANSFERCMD_SHARED *psTransferCmd;
+       struct PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
+       u32 i;
+       enum PVRSRV_ERROR eError;
+
+       if (!CCB_OFFSET_IS_VALID
+           (struct PVR3DIF4_TRANSFERCMD_SHARED, psCCBMemInfo, psKick,
+            ui32SharedCmdCCBOffset)) {
+               PVR_DPF(PVR_DBG_ERROR,
+                        "SGXSubmitTransferKM: Invalid CCB offset");
+               return PVRSRV_ERROR_INVALID_PARAMS;
+       }
+       psTransferCmd = CCB_DATA_FROM_OFFSET(struct PVR3DIF4_TRANSFERCMD_SHARED,
+                                            psCCBMemInfo, psKick,
+                                            ui32SharedCmdCCBOffset);
+
+       if (psTransferCmd->ui32NumStatusVals > SGXTQ_MAX_STATUS)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       if (psKick->ui32StatusFirstSync +
+           (psKick->ui32NumSrcSync ? (psKick->ui32NumSrcSync - 1) : 0) +
+           (psKick->ui32NumDstSync ? (psKick->ui32NumDstSync - 1) : 0) >
+           psTransferCmd->ui32NumStatusVals)
+               return PVRSRV_ERROR_INVALID_PARAMS;
+
+       if (psKick->hTASyncInfo != NULL) {
+               psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+                       psKick->hTASyncInfo;
+
+               psTransferCmd->ui32TASyncWriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psTransferCmd->ui32TASyncReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sTASyncWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->sTASyncReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       } else {
+               psTransferCmd->sTASyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psTransferCmd->sTASyncReadOpsCompleteDevVAddr.uiAddr = 0;
+       }
+
+       if (psKick->h3DSyncInfo != NULL) {
+               psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+                                                       psKick->h3DSyncInfo;
+
+               psTransferCmd->ui323DSyncWriteOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending++;
+               psTransferCmd->ui323DSyncReadOpsPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->s3DSyncWriteOpsCompleteDevVAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->s3DSyncReadOpsCompleteDevVAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       } else {
+               psTransferCmd->s3DSyncWriteOpsCompleteDevVAddr.uiAddr = 0;
+               psTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
+       }
+
+       psTransferCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
+       psTransferCmd->ui32NumDstSync = psKick->ui32NumDstSync;
+
+       if (psKick->ui32NumSrcSync > 0) {
+               psSyncInfo =
+                   (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[0];
+
+               psTransferCmd->ui32SrcWriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               psTransferCmd->ui32SrcReadOpPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sSrcWriteOpsCompleteDevAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->sSrcReadOpsCompleteDevAddr =
+                   psSyncInfo->sReadOpsCompleteDevVAddr;
+       }
+       if (psKick->ui32NumDstSync > 0) {
+               psSyncInfo =
+                   (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[0];
+
+               psTransferCmd->ui32DstWriteOpPendingVal =
+                   psSyncInfo->psSyncData->ui32WriteOpsPending;
+               psTransferCmd->ui32DstReadOpPendingVal =
+                   psSyncInfo->psSyncData->ui32ReadOpsPending;
+
+               psTransferCmd->sDstWriteOpsCompleteDevAddr =
+                   psSyncInfo->sWriteOpsCompleteDevVAddr;
+               psTransferCmd->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->ui32NumSrcSync > 1)
+               for (i = 1; i < psKick->ui32NumSrcSync; i++) {
+                       psSyncInfo =
+                           (struct PVRSRV_KERNEL_SYNC_INFO *)psKick->
+                           ahSrcSyncInfo[i];
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                             ui32StatusFirstSync].ui32StatusValue =
+                                 psSyncInfo->psSyncData->ui32ReadOpsPending++;
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                             ui32StatusFirstSync].sStatusDevAddr =
+                                 psSyncInfo->sReadOpsCompleteDevVAddr;
+
+                       psKick->ui32StatusFirstSync++;
+               }
+
+       if (psKick->ui32NumDstSync > 1)
+               for (i = 1; i < psKick->ui32NumDstSync; i++) {
+                       psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+                               psKick->ahDstSyncInfo[i];
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                           ui32StatusFirstSync].ui32StatusValue =
+                                psSyncInfo->psSyncData->ui32WriteOpsPending++;
+
+                       psTransferCmd->sCtlStatusInfo[psKick->
+                           ui32StatusFirstSync].sStatusDevAddr =
+                                psSyncInfo->sWriteOpsCompleteDevVAddr;
+
+                       psKick->ui32StatusFirstSync++;
+               }
+#if defined(PDUMP)
+       if (PDumpIsCaptureFrameKM()) {
+               PDUMPCOMMENT("Shared part of transfer command\r\n");
+               PDUMPMEM(psTransferCmd, psCCBMemInfo, psKick->ui32CCBDumpWOff,
+                        sizeof(struct PVR3DIF4_TRANSFERCMD_SHARED), 0,
+                        MAKEUNIQUETAG(psCCBMemInfo));
+
+               if (psKick->ui32NumSrcSync > 0) {
+                       psSyncInfo = psKick->ahSrcSyncInfo[0];
+
+                       PDUMPCOMMENT
+                           ("Hack src surface write op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo, psKick->ui32CCBDumpWOff +
+                                   offsetof(struct PVR3DIF4_TRANSFERCMD_SHARED,
+                                           ui32SrcWriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT
+                           ("Hack src surface read op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo, psKick->ui32CCBDumpWOff +
+                                   offsetof(struct PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32SrcReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+               if (psKick->ui32NumDstSync > 0) {
+                       psSyncInfo = psKick->ahDstSyncInfo[0];
+
+                       PDUMPCOMMENT
+                           ("Hack dest surface write op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
+                                psCCBMemInfo, psKick->ui32CCBDumpWOff +
+                                   offsetof(struct PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32DstWriteOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+
+                       PDUMPCOMMENT
+                           ("Hack dest surface read op in transfer cmd\r\n");
+                       PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+                                psCCBMemInfo, psKick->ui32CCBDumpWOff +
+                                   offsetof(struct PVR3DIF4_TRANSFERCMD_SHARED,
+                                         ui32DstReadOpPendingVal),
+                                sizeof(psSyncInfo->psSyncData->
+                                       ui32LastReadOpDumpVal), 0,
+                                MAKEUNIQUETAG(psCCBMemInfo));
+               }
+
+               if (psKick->ui32NumSrcSync > 0) {
+                       psSyncInfo = (struct PVRSRV_KERNEL_SYNC_INFO *)
+                               psKick->ahSrcSyncInfo[0];
+                       psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
+
+               }
+               if (psKick->ui32NumDstSync > 0) {
+                       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;
+
+       eError =
+           SGXScheduleCCBCommandKM(hDevHandle, PVRSRV_SGX_COMMAND_EDM_KICK,
+                                   &sCommand, KERNEL_ID);
+
+
+       return eError;
+}
+