1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2011 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 #include "dp/nvdp-device.h" 25 #include "nvdp-connector-event-sink.hpp" 26 #include "dp/nvdp-connector-event-sink.h" 27 28 #include "nvkms-types.h" 29 #include "nvkms-rm.h" 30 #include "nvkms-dpy.h" 31 32 #include "nvctassert.h" 33 34 void nvDPDeviceSetPowerState(NVDpyEvoPtr pDpyEvo, NvBool on) 35 { 36 NVDispEvoPtr pDispEvo = pDpyEvo->pDispEvo; 37 NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo; 38 39 if (!pDpyEvo->dp.pDpLibDevice) { 40 return; 41 } 42 43 nvAssert(nvDpyUsesDPLib(pDpyEvo)); 44 45 DisplayPort::Device *device = pDpyEvo->dp.pDpLibDevice->device; 46 47 nvRMSyncEvoChannel(pDevEvo, pDevEvo->core, __LINE__); 48 device->setPanelPowerParams(on, on); 49 50 /* 51 * WAR: Some monitors clear the MSA_TIMING_PAR_IGNORE_EN bit in the 52 * DOWNSPREAD_CTRL DPCD register after changing power state, which will 53 * cause the monitor to fail to restore the image after powering back on 54 * while VRR flipping. To work around this, re-enable Adaptive-Sync 55 * immediately after powering on. (Bug 200488547) 56 */ 57 if (nvDpyIsAdaptiveSync(pDpyEvo) && on) { 58 NVConnectorEvoRec *pConnectorEvo = pDpyEvo->pConnectorEvo; 59 NVDPLibConnectorPtr pDpLibConnector = pConnectorEvo->pDpLibConnector; 60 NvU32 head; 61 62 for (head = 0; head < pDevEvo->numHeads; head++) { 63 if (nvDpyIdIsInDpyIdList(pDpyEvo->id, 64 pDpLibConnector->dpyIdList[head]) && 65 (pDispEvo->headState[head].timings.vrr.type != 66 NVKMS_DPY_VRR_TYPE_NONE)) { 67 nvDPLibSetAdaptiveSync(pDispEvo, head, TRUE); 68 break; 69 } 70 } 71 } 72 } 73 74 unsigned int nvDPGetEDIDSize(const NVDpyEvoRec *pDpyEvo) 75 { 76 NVDPLibDevicePtr pDpLibDevice = pDpyEvo->dp.pDpLibDevice; 77 78 nvAssert(nvDpyUsesDPLib(pDpyEvo)); 79 80 if (!pDpLibDevice) { 81 return 0; 82 } 83 84 return pDpLibDevice->device->getEDIDSize(); 85 } 86 87 NvBool nvDPGetEDID(const NVDpyEvoRec *pDpyEvo, void *buffer, unsigned int size) 88 { 89 NVDPLibDevicePtr pDpLibDevice = pDpyEvo->dp.pDpLibDevice; 90 91 nvAssert(nvDpyUsesDPLib(pDpyEvo)); 92 93 if (!pDpLibDevice) { 94 return FALSE; 95 } 96 97 return pDpLibDevice->device->getEDID((char *)buffer, size); 98 } 99 100 void nvDPGetDpyGUID(NVDpyEvoPtr pDpyEvo) 101 { 102 NVDPLibDevicePtr pDpLibDevice; 103 const char *str; 104 105 nvkms_memset(&pDpyEvo->dp.guid, 0, sizeof(pDpyEvo->dp.guid)); 106 107 ct_assert(sizeof(pDpyEvo->dp.guid.buffer) == DPCD_GUID_SIZE); 108 109 if (!nvDpyUsesDPLib(pDpyEvo)) { 110 return; 111 } 112 113 pDpLibDevice = pDpyEvo->dp.pDpLibDevice; 114 if (!pDpLibDevice) { 115 return; 116 } 117 118 pDpyEvo->dp.guid.valid = 119 nvkmsDisplayPort::nvDPGetDeviceGUID(pDpLibDevice->device, 120 pDpyEvo->dp.guid.buffer) == true; 121 if (!pDpyEvo->dp.guid.valid) { 122 return; 123 } 124 125 str = nvkmsDisplayPort::nvDPGetDeviceGUIDStr(pDpLibDevice->device); 126 if (str != NULL) { 127 nvkms_strncpy(pDpyEvo->dp.guid.str, str, sizeof(pDpyEvo->dp.guid.str)); 128 } else { 129 pDpyEvo->dp.guid.valid = FALSE; 130 } 131 } 132 133 // Perform a fake lostDevice during device teardown. This function is called by 134 // DpyFree before it deletes a pDpy. 135 void nvDPDpyFree(NVDpyEvoPtr pDpyEvo) 136 { 137 if (!nvDpyUsesDPLib(pDpyEvo)) { 138 return; 139 } 140 141 if (!pDpyEvo->dp.pDpLibDevice) { 142 return; 143 } 144 145 DisplayPort::Device *device = pDpyEvo->dp.pDpLibDevice->device; 146 147 pDpyEvo->pConnectorEvo->pDpLibConnector->evtSink->lostDevice(device); 148 } 149 150 NvBool nvDPDpyIsDscPossible(const NVDpyEvoRec *pDpyEvo) 151 { 152 if (!nvDpyUsesDPLib(pDpyEvo) || 153 (pDpyEvo->dp.pDpLibDevice == NULL)) { 154 return FALSE; 155 } 156 return pDpyEvo->dp.pDpLibDevice->device->isDSCPossible(); 157 } 158