1 /* 2 * SPDX-FileCopyrightText: Copyright (c)2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /****************************************************************************** 25 * 26 * VblankCallback Module 27 * This file contains functions managing the vblank callback. 28 * 29 ******************************************************************************/ 30 31 #include "gpu/disp/vblank_callback/vblank_callback.h" 32 #include "os/os.h" 33 #include "gpu/disp/kern_disp.h" 34 #include "gpu/disp/head/kernel_head.h" 35 36 static NV_STATUS 37 _vblankCallback 38 ( 39 OBJGPU *pGpu, 40 void *pObject, 41 NvU32 Parm1, 42 NvU32 Parm2, 43 NV_STATUS rmStatus 44 ) 45 { 46 VblankCallback *pVblankCallback = (VblankCallback *)pObject; 47 if (pVblankCallback->CallBack.bIsVblankNotifyEnable) 48 { 49 pVblankCallback->pProc(pVblankCallback->pParm1, pVblankCallback->pParm2); 50 } 51 return NV_OK; 52 } 53 54 NV_STATUS 55 vblcbConstruct_IMPL 56 ( 57 VblankCallback *pVblankCallback, 58 CALL_CONTEXT *pCallContext, 59 RS_RES_ALLOC_PARAMS_INTERNAL *pParams 60 ) 61 { 62 OBJSYS *pSys = SYS_GET_INSTANCE(); 63 OBJOS *pOS = SYS_GET_OS(pSys); 64 OBJGPU *pGpu = GPU_RES_GET_GPU(pVblankCallback); 65 KernelDisplay *pKernelDisplay = GPU_GET_KERNEL_DISPLAY(pGpu); 66 KernelHead *pKernelHead = NULL; 67 NV_STATUS status = NV_OK; 68 NV_VBLANK_CALLBACK_ALLOCATION_PARAMETERS *pAllocParams = pParams->pAllocParams; 69 70 if (pKernelDisplay == NULL) 71 { 72 return NV_ERR_NOT_SUPPORTED; 73 } 74 75 pKernelHead = KDISP_GET_HEAD(pKernelDisplay, pAllocParams->LogicalHead); 76 77 if (pKernelHead == NULL) 78 { 79 return NV_ERR_INVALID_ARGUMENT; 80 } 81 82 pVblankCallback->LogicalHead = pAllocParams->LogicalHead; 83 pVblankCallback->pProc = pAllocParams->pProc; 84 pVblankCallback->pParm1 = pAllocParams->pParm1; 85 pVblankCallback->pParm2 = pAllocParams->pParm2; 86 pVblankCallback->CallBack.Flags = VBLANK_CALLBACK_FLAG_LOW_LATENCY | VBLANK_CALLBACK_FLAG_PERSISTENT | VBLANK_CALLBACK_FLAG_SPECIFIED_VBLANK_NEXT; 87 pVblankCallback->CallBack.Proc = _vblankCallback; 88 pVblankCallback->CallBack.pObject = pVblankCallback; 89 pVblankCallback->CallBack.bObjectIsChannelDescendant = NV_FALSE; 90 pVblankCallback->CallBack.Param1 = 0; 91 pVblankCallback->CallBack.Param2 = 0; 92 pVblankCallback->CallBack.VBlankCount = 0; 93 pVblankCallback->CallBack.VBlankOffset = 0; 94 pVblankCallback->CallBack.TimeStamp = 0; 95 pVblankCallback->CallBack.MC_CallbackFlag = 0; 96 pVblankCallback->CallBack.Status = NV_OK; 97 pVblankCallback->CallBack.bIsVblankNotifyEnable = NV_TRUE; 98 pVblankCallback->CallBack.Next = NULL; 99 100 kheadAddVblankCallback(pGpu, pKernelHead, &pVblankCallback->CallBack); 101 status = pOS->osSetupVBlank(pGpu, pAllocParams->pProc, pAllocParams->pParm1, pAllocParams->pParm2, pAllocParams->LogicalHead, &pVblankCallback->CallBack); 102 103 if (status != NV_OK) 104 { 105 kheadDeleteVblankCallback(pGpu, pKernelHead, &pVblankCallback->CallBack); 106 } 107 108 return status; 109 } 110 111 void 112 vblcbDestruct_IMPL 113 ( 114 VblankCallback *pVblankCallback 115 ) 116 { 117 OBJSYS *pSys = SYS_GET_INSTANCE(); 118 OBJOS *pOS = SYS_GET_OS(pSys); 119 OBJGPU *pGpu = GPU_RES_GET_GPU(pVblankCallback); 120 KernelDisplay *pKernelDisplay = GPU_GET_KERNEL_DISPLAY(pGpu); 121 KernelHead *pKernelHead = KDISP_GET_HEAD(pKernelDisplay, pVblankCallback->LogicalHead); 122 123 pOS->osSetupVBlank(pGpu, NULL, NULL, NULL, pVblankCallback->LogicalHead, NULL); 124 kheadDeleteVblankCallback(pGpu, pKernelHead, &pVblankCallback->CallBack); 125 } 126 127 NV_STATUS 128 vblcbCtrlSetVBlankNotification_IMPL 129 ( 130 VblankCallback *pVblankCallback, 131 NV9010_CTRL_CMD_SET_VBLANK_NOTIFICATION_PARAMS *pParams 132 ) 133 { 134 OBJGPU *pGpu = GPU_RES_GET_GPU(pVblankCallback); 135 KernelDisplay *pKernelDisplay = GPU_GET_KERNEL_DISPLAY(pGpu); 136 KernelHead *pKernelHead = KDISP_GET_HEAD(pKernelDisplay, pVblankCallback->LogicalHead); 137 NV_STATUS status = NV_ERR_INVALID_ARGUMENT; 138 if (pVblankCallback->CallBack.Proc != NULL) 139 { 140 if (pParams->bSetVBlankNotifyEnable) 141 { 142 pVblankCallback->CallBack.bIsVblankNotifyEnable = NV_TRUE; 143 kheadAddVblankCallback(pGpu, pKernelHead, &pVblankCallback->CallBack); 144 } 145 else 146 { 147 pVblankCallback->CallBack.bIsVblankNotifyEnable = NV_FALSE; 148 kheadDeleteVblankCallback(pGpu, pKernelHead, &pVblankCallback->CallBack); 149 } 150 status = NV_OK; 151 } 152 return status; 153 } 154 155