1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2014 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 "nvkms-dma.h"
25 #include "nvkms-evo.h"
26 #include "nvkms-hw-flip.h"
27 #include "nvkms-utils-flip.h"
28 #include "nvkms-flip-workarea.h"
29 #include "nvkms-surface.h"
30 #include "nvkms-prealloc.h"
31 #include "nvkms-private.h"
32 #include "nvkms-rm.h"
33 #include "nvkms-vrr.h"
34 #include "nvkms-cursor.h"
35 #include "nvkms-types.h"
36 #include "nvkms-dpy.h"
37 #include "nvkms-lut.h"
38 #include "nvkms-softfloat.h"
39 #include "nvkms-ctxdma.h"
40
41 #include "nvkms-sync.h"
42
43 #include "nvkms-difr.h"
44
45 static void SchedulePostFlipIMPTimer(NVDevEvoPtr pDevEvo);
46
47 // The EVO .mfs file defines the maximum minPresentInterval to be 8.
48 #define NV_MAX_SWAP_INTERVAL 8
49
AssignPreSyncptEvoHwState(const NVDevEvoRec * pDevEvo,const struct NvKmsChannelSyncObjects * pChannelSyncObjects,NVFlipSyncObjectEvoHwState * pFlipSyncObject)50 static NvBool AssignPreSyncptEvoHwState(
51 const NVDevEvoRec *pDevEvo,
52 const struct NvKmsChannelSyncObjects *pChannelSyncObjects,
53 NVFlipSyncObjectEvoHwState *pFlipSyncObject)
54 {
55 NvBool ret;
56 NvU32 id = 0;
57 NvU32 value;
58 enum NvKmsSyncptType preType;
59
60 nvAssert(pChannelSyncObjects->useSyncpt);
61
62 preType = pChannelSyncObjects->u.syncpts.pre.type;
63
64 if (preType == NVKMS_SYNCPT_TYPE_NONE) {
65 return TRUE;
66 }
67
68 if (preType == NVKMS_SYNCPT_TYPE_FD) {
69 /*! Get id from fd using nvhost API */
70 NvKmsSyncPtOpParams params = { };
71 params.fd_to_id_and_thresh.fd =
72 pChannelSyncObjects->u.syncpts.pre.u.fd;
73 ret = nvkms_syncpt_op(NVKMS_SYNCPT_OP_FD_TO_ID_AND_THRESH,
74 ¶ms);
75 if (!ret) {
76 return FALSE;
77 }
78 id = params.fd_to_id_and_thresh.id;
79 value = params.fd_to_id_and_thresh.thresh;
80 } else {
81 id = pChannelSyncObjects->u.syncpts.pre.u.raw.id;
82 value = pChannelSyncObjects->u.syncpts.pre.u.raw.value;
83 }
84 if (id >= NV_SYNCPT_GLOBAL_TABLE_LENGTH) {
85 return FALSE;
86 }
87 /*! Fill pre-syncpt related information in hardware state */
88 pFlipSyncObject->u.syncpts.preSyncpt = id;
89 pFlipSyncObject->u.syncpts.preValue = value;
90 pFlipSyncObject->u.syncpts.isPreSyncptSpecified = TRUE;
91 pFlipSyncObject->usingSyncpt = TRUE;
92
93 return TRUE;
94 }
95
AssignPostSyncptEvoHwState(const NVDevEvoRec * pDevEvo,NVEvoChannel * pChannel,const struct NvKmsChannelSyncObjects * pChannelSyncObjects,NVFlipSyncObjectEvoHwState * pFlipSyncObject)96 static NvBool AssignPostSyncptEvoHwState(
97 const NVDevEvoRec *pDevEvo,
98 NVEvoChannel *pChannel,
99 const struct NvKmsChannelSyncObjects *pChannelSyncObjects,
100 NVFlipSyncObjectEvoHwState *pFlipSyncObject)
101 {
102 enum NvKmsSyncptType postType;
103 NvU32 threshold;
104
105 nvAssert(pChannelSyncObjects->useSyncpt);
106
107 postType = pChannelSyncObjects->u.syncpts.requestedPostType;
108
109 /*!
110 * It is possible that syncpt is mentioned but post-syncpt
111 * is not specified (case where only pre-syncpt used)
112 */
113 if (postType == NVKMS_SYNCPT_TYPE_NONE) {
114 return TRUE;
115 }
116
117 /*! return threshold to caller but increase only when programming hw */
118 threshold = pChannel->postSyncpt.syncptMaxVal + 1;
119
120 /*! each channel associated with one post-syncpt */
121 pFlipSyncObject->u.syncpts.surfaceDesc =
122 pChannel->postSyncpt.surfaceDesc;
123 pFlipSyncObject->u.syncpts.postValue = threshold;
124
125 /*
126 * AllocPostSyncptPerChannel()->AllocSyncpt() sets allocated to TRUE
127 * when postSyncpt is allocated/valid.
128 */
129 pFlipSyncObject->u.syncpts.isPostSyncptSpecified =
130 pChannel->postSyncpt.allocated;
131
132 pFlipSyncObject->usingSyncpt = TRUE;
133
134 return TRUE;
135 }
136
nvFillPostSyncptReplyOneChannel(NVEvoChannel * pChannel,enum NvKmsSyncptType postType,struct NvKmsSyncpt * postSyncpt,const NVFlipSyncObjectEvoHwState * pHwSyncObject)137 void nvFillPostSyncptReplyOneChannel(
138 NVEvoChannel *pChannel,
139 enum NvKmsSyncptType postType,
140 struct NvKmsSyncpt *postSyncpt,
141 const NVFlipSyncObjectEvoHwState *pHwSyncObject)
142 {
143 if (postType == NVKMS_SYNCPT_TYPE_RAW) {
144 postSyncpt->u.raw.id = pChannel->postSyncpt.id;
145 postSyncpt->u.raw.value = pHwSyncObject->u.syncpts.postValue;
146 postSyncpt->type = NVKMS_SYNCPT_TYPE_RAW;
147 } else if (postType == NVKMS_SYNCPT_TYPE_FD) {
148 NvBool ret = TRUE;
149 NvKmsSyncPtOpParams params = { };
150 params.id_and_thresh_to_fd.id = pChannel->postSyncpt.id;
151 params.id_and_thresh_to_fd.thresh =
152 pHwSyncObject->u.syncpts.postValue;
153
154 ret = nvkms_syncpt_op(NVKMS_SYNCPT_OP_ID_AND_THRESH_TO_FD, ¶ms);
155 if (!ret) {
156 nvAssert(!"Failed syncpt op ID_AND_THRESH_TO_FD");
157 return;
158 }
159 postSyncpt->u.fd = params.id_and_thresh_to_fd.fd;
160 postSyncpt->type = NVKMS_SYNCPT_TYPE_FD;
161 }
162 }
163
nvClearFlipEvoHwState(NVFlipEvoHwState * pFlipState)164 void nvClearFlipEvoHwState(
165 NVFlipEvoHwState *pFlipState)
166 {
167 NvU32 i;
168
169 nvkms_memset(pFlipState, 0, sizeof(*pFlipState));
170
171 for (i = 0; i < ARRAY_LEN(pFlipState->layer); i++) {
172 pFlipState->layer[i].cscMatrix = NVKMS_IDENTITY_CSC_MATRIX;
173 }
174 }
175
176 /*!
177 * Initialize NVFlipEvoHwState with a current snapshot from headState.
178 */
nvInitFlipEvoHwState(const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,NVFlipEvoHwState * pFlipState)179 void nvInitFlipEvoHwState(
180 const NVDevEvoRec *pDevEvo,
181 const NvU32 sd,
182 const NvU32 head,
183 NVFlipEvoHwState *pFlipState)
184 {
185 NVDispEvoRec *pDispEvo = pDevEvo->gpus[sd].pDispEvo;
186 const NVEvoSubDevHeadStateRec *pSdHeadState;
187 const NVDispHeadStateEvoRec *pHeadState;
188
189 NvU32 i;
190
191 nvClearFlipEvoHwState(pFlipState);
192
193 if (!nvHeadIsActive(pDispEvo, head)) {
194 return;
195 }
196
197 pSdHeadState = &pDevEvo->gpus[sd].headState[head];
198 pHeadState = &pDispEvo->headState[head];
199
200 pFlipState->viewPortPointIn = pSdHeadState->viewPortPointIn;
201 pFlipState->cursor = pSdHeadState->cursor;
202
203 ct_assert(ARRAY_LEN(pFlipState->layer) == ARRAY_LEN(pSdHeadState->layer));
204
205 for (i = 0; i < ARRAY_LEN(pFlipState->layer); i++) {
206 pFlipState->layer[i] = pSdHeadState->layer[i];
207 }
208
209 // pFlipState->usage describes the usage bounds that will be necessary after
210 // this flip is complete. Initialize it using pSdHeadState->targetUsage,
211 // which describes the usage bounds that will be required just before this
212 // flip occurs, rather than pSdHeadState->usage, which describes the usage
213 // bounds currently programmed into the hardware.
214 //
215 // pSdHeadState->usage may have higher bounds than pSdHeadState->targetUsage
216 // if TryLoweringUsageBounds has not yet noticed that a satellite channel is
217 // no longer in use, or a flip to NULL in a satellite channel is pending but
218 // has not yet occurred.
219 pFlipState->usage = pSdHeadState->targetUsage;
220
221 pFlipState->disableMidFrameAndDWCFWatermark =
222 pSdHeadState->targetDisableMidFrameAndDWCFWatermark;
223
224 pFlipState->tf = pHeadState->tf;
225
226 pFlipState->hdrInfoFrame.enabled = pHeadState->hdrInfoFrameOverride.enabled;
227 pFlipState->hdrInfoFrame.eotf = pHeadState->hdrInfoFrameOverride.eotf;
228 pFlipState->hdrInfoFrame.staticMetadata =
229 pHeadState->hdrInfoFrameOverride.staticMetadata;
230
231 pFlipState->colorimetry = pHeadState->colorimetry;
232 }
233
234
nvIsLayerDirty(const struct NvKmsFlipCommonParams * pParams,const NvU32 layer)235 NvBool nvIsLayerDirty(const struct NvKmsFlipCommonParams *pParams,
236 const NvU32 layer)
237 {
238 return pParams->layer[layer].surface.specified ||
239 pParams->layer[layer].sizeIn.specified ||
240 pParams->layer[layer].sizeOut.specified ||
241 pParams->layer[layer].outputPosition.specified ||
242 pParams->layer[layer].completionNotifier.specified ||
243 pParams->layer[layer].syncObjects.specified ||
244 pParams->layer[layer].compositionParams.specified ||
245 pParams->layer[layer].csc.specified ||
246 pParams->layer[layer].hdr.specified ||
247 pParams->layer[layer].colorSpace.specified;
248 }
249
250 /*!
251 * Determine whether a base channel flip requires a non-tearing present mode.
252 *
253 * EVO requires a non-tearing flip when certain parameters are changing. See
254 * NV_DISP_BASE_STATE_ERROR_052 in dispClass024XBaseUpdateErrorChecks.mfs.
255 */
FlipRequiresNonTearingMode(const NVDevEvoRec * pDevEvo,const NvU32 head,const NVFlipChannelEvoHwState * pOld,const NVFlipChannelEvoHwState * pNew)256 static NvBool FlipRequiresNonTearingMode(
257 const NVDevEvoRec *pDevEvo,
258 const NvU32 head,
259 const NVFlipChannelEvoHwState *pOld,
260 const NVFlipChannelEvoHwState *pNew)
261 {
262 // TODO: Do we need to care about the right eye here? The error check
263 // doesn't.
264 const NVSurfaceEvoRec *pOldSurf = pOld->pSurfaceEvo[NVKMS_LEFT];
265 const NVSurfaceEvoRec *pNewSurf = pNew->pSurfaceEvo[NVKMS_LEFT];
266 NvU32 oldHwFormat = 0, newHwFormat = 0;
267
268 if (pOldSurf == NULL || pNewSurf == NULL) {
269 return TRUE;
270 }
271
272 // If these functions actually return FALSE at this point, then something is
273 // really wrong...
274 if (!pDevEvo->hal->ValidateWindowFormat(
275 pOldSurf->format, NULL, &oldHwFormat)) {
276 nvAssert(FALSE);
277 }
278
279 if (!pDevEvo->hal->ValidateWindowFormat(
280 pNewSurf->format, NULL, &newHwFormat)) {
281 nvAssert(FALSE);
282 }
283
284 // Commented entries are things checked in the .mfs that are not yet
285 // supported in NVKMS.
286 return // SuperSample
287 oldHwFormat != newHwFormat ||
288 // Gamma
289 // Layout (i.e. frame, field1, or field2)
290 pOldSurf->widthInPixels != pNewSurf->widthInPixels ||
291 pOldSurf->heightInPixels != pNewSurf->heightInPixels ||
292 pOldSurf->layout != pNewSurf->layout;
293 // UseGainOfs
294 // NewBaseLut -- USE_CORE_LUT is programmed in InitChannel*
295 // NewOutputLut
296 }
297
298
299 /*!
300 * Apply flip overrides if necessary.
301 *
302 * 1. Override swap intervals for VRR.
303 * 2. If the flip is changing certain parameters, override the tearing mode.
304 */
ApplyBaseFlipOverrides(const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,NVFlipChannelEvoHwState * pNew,NvBool allowVrr)305 static NvBool ApplyBaseFlipOverrides(
306 const NVDevEvoRec *pDevEvo,
307 const NvU32 sd,
308 const NvU32 head,
309 NVFlipChannelEvoHwState *pNew,
310 NvBool allowVrr)
311 {
312 const NVDispEvoRec *pDispEvo = pDevEvo->gpus[sd].pDispEvo;
313 const NVFlipChannelEvoHwState *pOld =
314 &pDevEvo->gpus[sd].headState[head].layer[NVKMS_MAIN_LAYER];
315
316 // Apply VRR swap interval overrides.
317 //
318 // Note that this applies the overrides whenever the client requests VRR and
319 // VRR is enabled, regardless of whether actually activating it later
320 // succeeds.
321 if (allowVrr) {
322 if (!nvHeadIsActive(pDispEvo, head)) {
323 //
324 // XXX If VRR is allowed then modeset should have happened before
325 // base channel flip, currently we don't know how to do modeset
326 // and program base channel for VRR at same time. This should be
327 // revisited as part of bug 1731279.
328 //
329 return FALSE;
330 }
331 nvApplyVrrBaseFlipOverrides(pDevEvo->gpus[sd].pDispEvo, head,
332 pOld, pNew);
333 }
334
335 if (!nvHeadIsActive(pDispEvo, head)) {
336 //
337 // This is possible when modeset and base flip happening at same time,
338 // tearing parameter does not make sense in that case,
339 // it should is disabled.
340 //
341 pNew->tearing = FALSE;
342 } else {
343 // Force non-tearing mode if EVO requires it.
344 if (FlipRequiresNonTearingMode(pDevEvo, head, pOld, pNew)) {
345 pNew->tearing = FALSE;
346 }
347 }
348
349 return TRUE;
350 }
351
ValidateScalingUsageBounds(const struct NvKmsScalingUsageBounds * pS,const struct NvKmsScalingUsageBounds * pMaxS)352 static NvBool ValidateScalingUsageBounds(
353 const struct NvKmsScalingUsageBounds *pS,
354 const struct NvKmsScalingUsageBounds *pMaxS)
355 {
356 return (pS->maxVDownscaleFactor <= pMaxS->maxVDownscaleFactor) &&
357 (pS->maxHDownscaleFactor <= pMaxS->maxHDownscaleFactor) &&
358 (pS->vTaps <= pMaxS->vTaps) &&
359 (!pS->vUpscalingAllowed || pMaxS->vUpscalingAllowed);
360 }
361
362 /*!
363 * Validate the requested usage bounds against the specified maximums.
364 */
ValidateUsageBounds(const NVDevEvoRec * pDevEvo,const NvU32 head,const struct NvKmsUsageBounds * pUsage,const struct NvKmsUsageBounds * pGuaranteedUsage)365 static NvBool ValidateUsageBounds(
366 const NVDevEvoRec *pDevEvo,
367 const NvU32 head,
368 const struct NvKmsUsageBounds *pUsage,
369 const struct NvKmsUsageBounds *pGuaranteedUsage)
370 {
371 NvU32 i;
372
373 for (i = 0; i < pDevEvo->head[head].numLayers; i++) {
374 const NvU64 supportedSurfaceFormatsUnion =
375 pUsage->layer[i].supportedSurfaceMemoryFormats |
376 pGuaranteedUsage->layer[i].supportedSurfaceMemoryFormats;
377
378 if ((pUsage->layer[i].usable && !pGuaranteedUsage->layer[i].usable) ||
379 (supportedSurfaceFormatsUnion !=
380 pGuaranteedUsage->layer[i].supportedSurfaceMemoryFormats) ||
381 !ValidateScalingUsageBounds(&pUsage->layer[i].scaling,
382 &pGuaranteedUsage->layer[i].scaling)) {
383 return FALSE;
384 }
385 }
386
387 return TRUE;
388 }
389
390 /*!
391 * Assign pFlipState->usage.
392 */
AssignUsageBounds(const NVDevEvoRec * pDevEvo,const NvU32 head,NVFlipEvoHwState * pFlipState)393 static NvBool AssignUsageBounds(
394 const NVDevEvoRec *pDevEvo,
395 const NvU32 head,
396 NVFlipEvoHwState *pFlipState)
397 {
398 struct NvKmsUsageBounds *pUsage = &pFlipState->usage;
399 int i;
400
401 for (i = 0; i < pDevEvo->head[head].numLayers; i++) {
402 const NVFlipChannelEvoHwState *pLayerFlipState = &pFlipState->layer[i];
403
404 nvInitScalingUsageBounds(pDevEvo, &pUsage->layer[i].scaling);
405
406 if (pLayerFlipState->pSurfaceEvo[NVKMS_LEFT]) {
407 pUsage->layer[i].usable = TRUE;
408 pUsage->layer[i].supportedSurfaceMemoryFormats =
409 nvEvoGetFormatsWithEqualOrLowerUsageBound(
410 pLayerFlipState->pSurfaceEvo[NVKMS_LEFT]->format,
411 pDevEvo->caps.layerCaps[i].supportedSurfaceMemoryFormats);
412
413 if (pDevEvo->hal->GetWindowScalingCaps) {
414 const NVEvoScalerCaps *pScalerCaps =
415 pDevEvo->hal->GetWindowScalingCaps(pDevEvo);
416
417 if (!nvComputeScalingUsageBounds(pScalerCaps,
418 pLayerFlipState->sizeIn.width,
419 pLayerFlipState->sizeIn.height,
420 pLayerFlipState->sizeOut.width,
421 pLayerFlipState->sizeOut.height,
422 pLayerFlipState->hTaps,
423 pLayerFlipState->vTaps,
424 &pUsage->layer[i].scaling)) {
425 return FALSE;
426 }
427 }
428
429 if (pLayerFlipState->maxDownscaleFactors.specified) {
430 struct NvKmsScalingUsageBounds *pTargetScaling =
431 &pFlipState->usage.layer[i].scaling;
432
433 if ((pLayerFlipState->maxDownscaleFactors.vertical <
434 pTargetScaling->maxVDownscaleFactor) ||
435 (pLayerFlipState->maxDownscaleFactors.horizontal <
436 pTargetScaling->maxHDownscaleFactor)) {
437 return FALSE;
438 }
439
440 pTargetScaling->maxVDownscaleFactor =
441 pLayerFlipState->maxDownscaleFactors.vertical;
442 pTargetScaling->maxHDownscaleFactor =
443 pLayerFlipState->maxDownscaleFactors.horizontal;
444 }
445
446 } else {
447 pUsage->layer[i].usable = FALSE;
448 pUsage->layer[i].supportedSurfaceMemoryFormats = 0;
449 }
450 }
451
452 return TRUE;
453 }
454
455 void
nvOverrideScalingUsageBounds(const NVDevEvoRec * pDevEvo,NvU32 head,NVFlipEvoHwState * pFlipState,const struct NvKmsUsageBounds * pPossibleUsage)456 nvOverrideScalingUsageBounds(const NVDevEvoRec *pDevEvo,
457 NvU32 head,
458 NVFlipEvoHwState *pFlipState,
459 const struct NvKmsUsageBounds *pPossibleUsage)
460 {
461 NvU32 i;
462
463 for (i = 0; i < pDevEvo->head[head].numLayers; i++) {
464 const NVFlipChannelEvoHwState *pLayerFlipState = &pFlipState->layer[i];
465 const struct NvKmsScalingUsageBounds *pPossibleScaling =
466 &pPossibleUsage->layer[i].scaling;
467 struct NvKmsScalingUsageBounds *pTargetScaling =
468 &pFlipState->usage.layer[i].scaling;
469
470 if (!pFlipState->usage.layer[i].usable) {
471 continue;
472 }
473
474 if (!pLayerFlipState->maxDownscaleFactors.specified) {
475 const NvU16 possibleV = pPossibleScaling->maxVDownscaleFactor;
476 const NvU16 possibleH = pPossibleScaling->maxHDownscaleFactor;
477 NvU16 targetV = pTargetScaling->maxVDownscaleFactor;
478 NvU16 targetH = pTargetScaling->maxHDownscaleFactor;
479
480 /*
481 * Calculate max H/V downscale factor by quantizing the range.
482 *
483 * E.g.,
484 * max H/V downscale factor supported by HW is 4x for 5-tap and 2x
485 * for 2-tap mode. If 5-tap mode is required, the target usage bound
486 * that nvkms will attempt to program will either allow up to 2x
487 * downscaling, or up to 4x downscaling. If 2-tap mode is required,
488 * the target usage bound that NVKMS will attempt to program will
489 * allow up to 2x downscaling. Example: to downscale from 4096x2160
490 * -> 2731x864 in 5-tap mode, NVKMS would specify up to 2x for the
491 * H downscale bound (required is 1.5x), and up to 4x for the V
492 * downscale bound (required is 2.5x).
493 */
494 if (targetV > NV_EVO_SCALE_FACTOR_1X) {
495 const NvU16 possibleMid =
496 NV_EVO_SCALE_FACTOR_1X + ((possibleV - NV_EVO_SCALE_FACTOR_1X) / 2);
497
498 if (targetV <= possibleMid) {
499 pTargetScaling->maxVDownscaleFactor = possibleMid;
500 } else {
501 pTargetScaling->maxVDownscaleFactor = possibleV;
502 }
503 }
504
505 if (targetH > NV_EVO_SCALE_FACTOR_1X) {
506 const NvU16 possibleMid =
507 NV_EVO_SCALE_FACTOR_1X + ((possibleH - NV_EVO_SCALE_FACTOR_1X) / 2);
508
509 if (targetH <= possibleMid) {
510 pTargetScaling->maxHDownscaleFactor = possibleMid;
511 } else {
512 pTargetScaling->maxHDownscaleFactor = possibleH;
513 }
514 }
515 }
516
517 pTargetScaling->vTaps = pPossibleScaling->vTaps;
518 pTargetScaling->vUpscalingAllowed = pPossibleScaling->vUpscalingAllowed;
519 }
520 }
521
FlipTimeStampValidForChannel(const NVEvoChannel * pChannel,NvU64 timeStamp)522 static NvBool FlipTimeStampValidForChannel(
523 const NVEvoChannel *pChannel,
524 NvU64 timeStamp)
525 {
526 if (pChannel->caps.validTimeStampBits < 64) {
527 const NvU64 validTimeStampMask =
528 NVBIT64(pChannel->caps.validTimeStampBits) - 1;
529 if ((timeStamp & ~validTimeStampMask) != 0) {
530 return FALSE;
531 }
532 }
533 return TRUE;
534 }
535
UpdateLayerFlipEvoHwStateHDRStaticMetadata(const NVDevEvoRec * pDevEvo,const struct NvKmsFlipCommonParams * pParams,NVFlipEvoHwState * pFlipState,NVFlipChannelEvoHwState * pHwState,const NvU32 head,const NvU32 layer)536 static NvBool UpdateLayerFlipEvoHwStateHDRStaticMetadata(
537 const NVDevEvoRec *pDevEvo,
538 const struct NvKmsFlipCommonParams *pParams,
539 NVFlipEvoHwState *pFlipState,
540 NVFlipChannelEvoHwState *pHwState,
541 const NvU32 head,
542 const NvU32 layer)
543 {
544 if (pParams->layer[layer].hdr.specified) {
545 if (pParams->layer[layer].hdr.enabled) {
546 // Don't allow enabling HDR on a layer that doesn't support it.
547 if (!pDevEvo->caps.layerCaps[layer].supportsHDR) {
548 return FALSE;
549 }
550
551 pHwState->hdrStaticMetadata.val =
552 pParams->layer[layer].hdr.staticMetadata;
553 }
554 pHwState->hdrStaticMetadata.enabled = pParams->layer[layer].hdr.enabled;
555
556 // Only mark dirty if layer supports HDR, otherwise this is a no-op.
557 if (pDevEvo->caps.layerCaps[layer].supportsHDR) {
558 pFlipState->dirty.hdrStaticMetadata = TRUE;
559 }
560 }
561
562 return TRUE;
563 }
564
UpdateLayerFlipEvoHwStateCommon(const struct NvKmsPerOpenDev * pOpenDev,const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,const NvU32 layer,const struct NvKmsFlipCommonParams * pParams,NVFlipEvoHwState * pFlipState)565 static NvBool UpdateLayerFlipEvoHwStateCommon(
566 const struct NvKmsPerOpenDev *pOpenDev,
567 const NVDevEvoRec *pDevEvo,
568 const NvU32 sd,
569 const NvU32 head,
570 const NvU32 layer,
571 const struct NvKmsFlipCommonParams *pParams,
572 NVFlipEvoHwState *pFlipState)
573 {
574 const NVEvoChannel *pChannel = pDevEvo->head[head].layer[layer];
575 NVFlipChannelEvoHwState *pHwState = &pFlipState->layer[layer];
576 const NVEvoApiHandlesRec *pOpenDevSurfaceHandles =
577 nvGetSurfaceHandlesFromOpenDevConst(pOpenDev);
578 NvBool ret;
579
580 if (pParams->layer[layer].surface.specified) {
581 ret = nvAssignSurfaceArray(pDevEvo,
582 pOpenDevSurfaceHandles,
583 pParams->layer[layer].surface.handle,
584 FALSE /* isUsedByCursorChannel */,
585 TRUE /* isUsedByLayerChannel */,
586 pHwState->pSurfaceEvo);
587 if (!ret) {
588 return FALSE;
589 }
590
591 /*
592 * Verify the (rotation, reflectionX, reflectionY) is a
593 * combination currently supported.
594 */
595 if ((NVBIT(NvKmsRRParamsToCapBit(&pParams->layer[layer].surface.rrParams)) &
596 pDevEvo->caps.validLayerRRTransforms) == 0) {
597 return FALSE;
598 }
599 pHwState->rrParams = pParams->layer[layer].surface.rrParams;
600
601 }
602
603 /* Verify the timestamp is in the valid range for this channel. */
604 if (!FlipTimeStampValidForChannel(pChannel,
605 pParams->layer[layer].timeStamp)) {
606 return FALSE;
607 }
608 pHwState->timeStamp = pParams->layer[layer].timeStamp;
609
610 if (pParams->layer[layer].syncObjects.specified) {
611 if (!pDevEvo->supportsSyncpts &&
612 pParams->layer[layer].syncObjects.val.useSyncpt) {
613 return FALSE;
614 }
615
616 nvkms_memset(&pFlipState->layer[layer].syncObject,
617 0,
618 sizeof(pFlipState->layer[layer].syncObject));
619
620 if (pParams->layer[layer].syncObjects.val.useSyncpt) {
621 ret = AssignPreSyncptEvoHwState(pDevEvo,
622 &pParams->layer[layer].syncObjects.val,
623 &pHwState->syncObject);
624 if (!ret) {
625 return FALSE;
626 }
627 pFlipState->dirty.layerSyncObjects[layer] = TRUE;
628
629 ret = AssignPostSyncptEvoHwState(pDevEvo,
630 pDevEvo->head[head].layer[layer],
631 &pParams->layer[layer].syncObjects.val,
632 &pHwState->syncObject);
633 if (!ret) {
634 return FALSE;
635 }
636 } else {
637 if (pParams->layer[layer].syncObjects.val.u.semaphores.acquire.surface.surfaceHandle != 0 ||
638 pParams->layer[layer].syncObjects.val.u.semaphores.release.surface.surfaceHandle != 0) {
639 if (pParams->layer[layer].skipPendingFlips) {
640 return FALSE;
641 }
642 }
643
644 ret = nvAssignSemaphoreEvoHwState(pDevEvo,
645 pOpenDevSurfaceHandles,
646 layer,
647 sd,
648 &pParams->layer[layer].syncObjects.val,
649 &pHwState->syncObject);
650 if (!ret) {
651 return FALSE;
652 }
653 }
654 }
655
656 if (pHwState->pSurfaceEvo[NVKMS_LEFT]) {
657 pHwState->minPresentInterval =
658 pParams->layer[layer].minPresentInterval;
659 } else {
660 /* The hardware requires that MPI be 0 when disabled. */
661 pHwState->minPresentInterval = 0;
662 }
663
664 if (pParams->layer[layer].sizeIn.specified) {
665 pHwState->sizeIn = pParams->layer[layer].sizeIn.val;
666 }
667
668 if (pParams->layer[layer].sizeOut.specified) {
669 pHwState->sizeOut = pParams->layer[layer].sizeOut.val;
670 }
671
672 /*
673 * If supportsWindowMode = TRUE, the sizeIn/sizeOut dimensions can be
674 * any arbitrary (valid) values.
675 *
676 * If supportsWindowMode = FALSE (legacy EVO main layer), the sizeIn
677 * /sizeOut dimensions must match the size of the surface for that layer.
678 *
679 * Note that if sizeIn/Out dimensions are invalid i.e. with a width or
680 * height of zero, this will be rejected by a call to
681 * ValidateFlipChannelEvoHwState() later in the code path.
682 *
683 * Note that if scaling is unsupported, i.e. that sizeIn cannot differ
684 * from sizeOut, then any unsupported configurations will be caught by the
685 * ComputeWindowScalingTaps() call later on in this function.
686 */
687 if (!pDevEvo->caps.layerCaps[layer].supportsWindowMode &&
688 (pHwState->pSurfaceEvo[NVKMS_LEFT] != NULL)) {
689 const NVSurfaceEvoRec *pSurfaceEvo =
690 pHwState->pSurfaceEvo[NVKMS_LEFT];
691
692 if ((pHwState->sizeIn.width != pSurfaceEvo->widthInPixels) ||
693 (pHwState->sizeIn.height != pSurfaceEvo->heightInPixels)) {
694 return FALSE;
695 }
696
697 if ((pHwState->sizeOut.width != pSurfaceEvo->widthInPixels) ||
698 (pHwState->sizeOut.height != pSurfaceEvo->heightInPixels)) {
699 return FALSE;
700 }
701 }
702
703 /*
704 * Allow the client to specify non-origin outputPosition only if the
705 * layer supports window mode.
706 *
707 * If window mode is unsupported but the client specifies non-origin
708 * outputPosition, return FALSE.
709 */
710 if (pDevEvo->caps.layerCaps[layer].supportsWindowMode) {
711 if (pParams->layer[layer].outputPosition.specified) {
712 const NvS16 x = pParams->layer[layer].outputPosition.val.x;
713 const NvS16 y = pParams->layer[layer].outputPosition.val.y;
714 if ((pHwState->outputPosition.x != x) ||
715 (pHwState->outputPosition.y != y)) {
716 pHwState->outputPosition.x = x;
717 pHwState->outputPosition.y = y;
718 pFlipState->dirty.layerPosition[layer] = TRUE;
719 }
720 }
721 } else if (pParams->layer[layer].outputPosition.specified &&
722 ((pParams->layer[layer].outputPosition.val.x != 0) ||
723 (pParams->layer[layer].outputPosition.val.y != 0))) {
724 return FALSE;
725 }
726
727 if (pParams->layer[layer].compositionParams.specified) {
728 pHwState->composition =
729 pParams->layer[layer].compositionParams.val;
730 }
731
732 if (!UpdateLayerFlipEvoHwStateHDRStaticMetadata(
733 pDevEvo, pParams, pFlipState,
734 pHwState, head, layer)) {
735 return FALSE;
736 }
737
738 if (pParams->layer[layer].colorRange.specified) {
739 pHwState->colorRange = pParams->layer[layer].colorRange.val;
740 }
741
742 if (pParams->layer[layer].colorSpace.specified) {
743 pHwState->colorSpace =
744 pParams->layer[layer].colorSpace.val;
745 }
746
747 if (pHwState->composition.depth == 0) {
748 pHwState->composition.depth =
749 NVKMS_MAX_LAYERS_PER_HEAD - layer;
750 }
751
752 /* XXX Move ValidatePerLayerCompParams() call to nvValidateFlipEvoHwState() */
753 if (!nvValidatePerLayerCompParams(
754 &pHwState->composition,
755 &pDevEvo->caps.layerCaps[layer].composition,
756 pHwState->pSurfaceEvo[NVKMS_LEFT])) {
757 return FALSE;
758 }
759
760 if (!pDevEvo->hal->ComputeWindowScalingTaps(pDevEvo,
761 pChannel,
762 pHwState)) {
763 return FALSE;
764 }
765
766 if (pParams->layer[layer].completionNotifier.specified) {
767 ret = nvAssignCompletionNotifierEvoHwState(
768 pDevEvo,
769 pOpenDevSurfaceHandles,
770 &pParams->layer[layer].completionNotifier.val,
771 layer,
772 &pFlipState->layer[layer].completionNotifier);
773 if (!ret) {
774 return FALSE;
775 }
776 }
777
778 if (pParams->layer[layer].maxDownscaleFactors.specified) {
779 pFlipState->layer[layer].maxDownscaleFactors.vertical =
780 pParams->layer[layer].maxDownscaleFactors.vertical;
781 pFlipState->layer[layer].maxDownscaleFactors.horizontal =
782 pParams->layer[layer].maxDownscaleFactors.horizontal;
783 pFlipState->layer[layer].maxDownscaleFactors.specified = TRUE;
784 } else {
785 pFlipState->layer[layer].maxDownscaleFactors.vertical = 0;
786 pFlipState->layer[layer].maxDownscaleFactors.horizontal = 0;
787 pFlipState->layer[layer].maxDownscaleFactors.specified = FALSE;
788 }
789
790 pFlipState->dirty.layer[layer] = TRUE;
791
792 return TRUE;
793 }
794
UpdateMainLayerFlipEvoHwState(const struct NvKmsPerOpenDev * pOpenDev,const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,const struct NvKmsFlipCommonParams * pParams,NVFlipEvoHwState * pFlipState,NvBool allowVrr)795 static NvBool UpdateMainLayerFlipEvoHwState(
796 const struct NvKmsPerOpenDev *pOpenDev,
797 const NVDevEvoRec *pDevEvo,
798 const NvU32 sd,
799 const NvU32 head,
800 const struct NvKmsFlipCommonParams *pParams,
801 NVFlipEvoHwState *pFlipState,
802 NvBool allowVrr)
803 {
804 const NVEvoChannel *pChannel =
805 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER];
806 NVFlipChannelEvoHwState *pHwState = &pFlipState->layer[NVKMS_MAIN_LAYER];
807
808 if (!nvIsLayerDirty(pParams, NVKMS_MAIN_LAYER)) {
809 return TRUE;
810 }
811
812 if (!UpdateLayerFlipEvoHwStateCommon(pOpenDev, pDevEvo, sd, head,
813 NVKMS_MAIN_LAYER,
814 pParams, pFlipState)) {
815 return FALSE;
816 }
817
818 if (pParams->layer[NVKMS_MAIN_LAYER].csc.specified) {
819 if (pParams->layer[NVKMS_MAIN_LAYER].csc.useMain) {
820 return FALSE;
821 } else {
822 pHwState->cscMatrix = pParams->layer[NVKMS_MAIN_LAYER].csc.matrix;
823 }
824 }
825
826 if (pParams->layer[NVKMS_MAIN_LAYER].surface.specified) {
827 if (pParams->layer[NVKMS_MAIN_LAYER].perEyeStereoFlip &&
828 !pChannel->caps.perEyeStereoFlips) {
829 return FALSE;
830 }
831
832 pHwState->perEyeStereoFlip =
833 pParams->layer[NVKMS_MAIN_LAYER].perEyeStereoFlip;
834 }
835
836 if (pParams->layer[NVKMS_MAIN_LAYER].tearing && !pChannel->caps.tearingFlips) {
837 return FALSE;
838 }
839
840 // EVO will throw an invalid argument exception if
841 // minPresentInterval is too large, or if tearing is enabled and
842 // it's not zero.
843 if (pParams->layer[NVKMS_MAIN_LAYER].minPresentInterval > NV_MAX_SWAP_INTERVAL ||
844 (pParams->layer[NVKMS_MAIN_LAYER].tearing &&
845 pParams->layer[NVKMS_MAIN_LAYER].minPresentInterval != 0)) {
846 return FALSE;
847 }
848
849 pHwState->tearing = pParams->layer[NVKMS_MAIN_LAYER].tearing;
850
851 /*
852 * XXX: Cludge. Ideally, this would be handled by FlipRequiresNonTearingMode
853 * recognizing a difference in HW state. However, the new HW LUT state is
854 * not computed until later, when nvEvoSetLut() and nvEvoSetLUTContextDma()
855 * are called. See bug 4054546.
856 */
857 if ((pParams->lut.input.specified ||
858 pParams->lut.output.specified) &&
859 !pDevEvo->hal->caps.supportsCoreLut) {
860
861 pHwState->tearing = FALSE;
862 }
863
864 if (!ApplyBaseFlipOverrides(pDevEvo,
865 sd, head, &pFlipState->layer[NVKMS_MAIN_LAYER],
866 allowVrr)) {
867 return FALSE;
868 }
869
870 pFlipState->skipLayerPendingFlips[NVKMS_MAIN_LAYER] =
871 pParams->layer[NVKMS_MAIN_LAYER].skipPendingFlips;
872
873 return TRUE;
874 }
875
UpdateCursorLayerFlipEvoHwState(const struct NvKmsPerOpenDev * pOpenDev,const NVDevEvoRec * pDevEvo,const struct NvKmsFlipCommonParams * pParams,const NVHwModeTimingsEvo * pTimings,const NvU8 tilePosition,NVFlipEvoHwState * pFlipState)876 static NvBool UpdateCursorLayerFlipEvoHwState(
877 const struct NvKmsPerOpenDev *pOpenDev,
878 const NVDevEvoRec *pDevEvo,
879 const struct NvKmsFlipCommonParams *pParams,
880 const NVHwModeTimingsEvo *pTimings,
881 const NvU8 tilePosition,
882 NVFlipEvoHwState *pFlipState)
883 {
884 if (pParams->cursor.imageSpecified) {
885 if (!nvAssignCursorSurface(pOpenDev, pDevEvo, &pParams->cursor.image,
886 &pFlipState->cursor.pSurfaceEvo)) {
887 return FALSE;
888 }
889
890 if (pFlipState->cursor.pSurfaceEvo != NULL) {
891 pFlipState->cursor.cursorCompParams =
892 pParams->cursor.image.cursorCompParams;
893 }
894
895 pFlipState->dirty.cursorSurface = TRUE;
896 }
897
898 if (pParams->cursor.positionSpecified) {
899 pFlipState->cursor.x = (pParams->cursor.position.x -
900 (pTimings->viewPort.in.width * tilePosition));
901 pFlipState->cursor.y = pParams->cursor.position.y;
902
903 pFlipState->dirty.cursorPosition = TRUE;
904 }
905
906 return TRUE;
907 }
908
UpdateOverlayLayerFlipEvoHwState(const struct NvKmsPerOpenDev * pOpenDev,const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,const NvU32 layer,const struct NvKmsFlipCommonParams * pParams,NVFlipEvoHwState * pFlipState)909 static NvBool UpdateOverlayLayerFlipEvoHwState(
910 const struct NvKmsPerOpenDev *pOpenDev,
911 const NVDevEvoRec *pDevEvo,
912 const NvU32 sd,
913 const NvU32 head,
914 const NvU32 layer,
915 const struct NvKmsFlipCommonParams *pParams,
916 NVFlipEvoHwState *pFlipState)
917 {
918 NVFlipChannelEvoHwState *pHwState = &pFlipState->layer[layer];
919
920 nvAssert(layer != NVKMS_MAIN_LAYER);
921
922 if (!nvIsLayerDirty(pParams, layer)) {
923 return TRUE;
924 }
925
926 if (pParams->layer[layer].skipPendingFlips ||
927 pParams->layer[layer].perEyeStereoFlip) {
928 return FALSE;
929 }
930
931 if (!UpdateLayerFlipEvoHwStateCommon(pOpenDev, pDevEvo, sd, head, layer,
932 pParams, pFlipState)) {
933 return FALSE;
934 }
935
936 if (pParams->layer[layer].csc.specified) {
937 if (pParams->layer[layer].csc.useMain) {
938 if (pFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT]) {
939 pHwState->cscMatrix =
940 pFlipState->layer[NVKMS_MAIN_LAYER].cscMatrix;
941 }
942 } else {
943 pHwState->cscMatrix = pParams->layer[layer].csc.matrix;
944 }
945 }
946
947 return TRUE;
948 }
949
950 /*!
951 * Update the NVFlipEvoHwState, using NvKmsFlipCommonParams.
952 *
953 * Propagate the requested configuration from NvKmsFlipCommonParams to
954 * NVFlipEvoHwState, performing steps such as translating from
955 * NvKmsSurfaceHandle to NVSurfaceEvoRecs. Validate the NvKmsFlipCommonParams
956 * parameters, but defer more general validation of the resulting
957 * NVFlipEvoHwState until nvValidateFlipEvoHwState(), which callers must call
958 * separately.
959 *
960 * The NVFlipEvoHwState should first be initialized by calling
961 * nvInitFlipEvoHwState().
962 *
963 * No NVKMS hardware or software state should be altered here, because
964 * this function is used before we have decided to commit the proposed
965 * NVFlipEvoHwState to hardware.
966 *
967 * \param[in] pOpenDev The pOpenDev of the client doing the flip.
968 * \param[in] pDevEvo The device on which the surface image will be set.
969 * \param[in] sd The subdevice for the flip, as specified by the
970 * client.
971 * \param[in] head The head for the flip, as specified by the client.
972 * \param[in] pParams The requested flip, NvKmsFlipCommonParams.
973 * \param[in] pTimings The mode timings for the flip.
974 * \param[in,out] pFlipState The resulting NVFlipEvoHwState.
975 * \param[in] allowVrr Whether VRR flipping should be allowed.
976 * \param[in] pPossibleUsage Possible usage.
977 *
978 * \return If pFlipState could be updated, return TRUE.
979 * Otherwise, return FALSE.
980 */
nvUpdateFlipEvoHwState(const struct NvKmsPerOpenDev * pOpenDev,const NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,const struct NvKmsFlipCommonParams * pParams,const NVHwModeTimingsEvo * pTimings,const NvU8 tilePosition,NVFlipEvoHwState * pFlipState,NvBool allowVrr)981 NvBool nvUpdateFlipEvoHwState(
982 const struct NvKmsPerOpenDev *pOpenDev,
983 const NVDevEvoRec *pDevEvo,
984 const NvU32 sd,
985 const NvU32 head,
986 const struct NvKmsFlipCommonParams *pParams,
987 const NVHwModeTimingsEvo *pTimings,
988 const NvU8 tilePosition,
989 NVFlipEvoHwState *pFlipState,
990 NvBool allowVrr)
991 {
992 NvU32 layer;
993
994 if (pParams->viewPortIn.specified) {
995 pFlipState->dirty.viewPortPointIn = TRUE;
996 pFlipState->viewPortPointIn.x = pParams->viewPortIn.point.x +
997 (pTimings->viewPort.in.width * tilePosition);
998 pFlipState->viewPortPointIn.y = pParams->viewPortIn.point.y;
999 }
1000
1001 if (!UpdateCursorLayerFlipEvoHwState(pOpenDev, pDevEvo, pParams, pTimings,
1002 tilePosition, pFlipState)) {
1003 return FALSE;
1004 }
1005
1006 if (pParams->tf.specified) {
1007 pFlipState->dirty.tf = TRUE;
1008 pFlipState->tf = pParams->tf.val;
1009 }
1010
1011 if (pParams->colorimetry.specified) {
1012 pFlipState->dirty.colorimetry = TRUE;
1013 pFlipState->colorimetry = pParams->colorimetry.val;
1014 }
1015
1016 if (pParams->hdrInfoFrame.specified) {
1017 pFlipState->dirty.hdrStaticMetadata = TRUE;
1018
1019 if (pParams->hdrInfoFrame.enabled) {
1020 pFlipState->hdrInfoFrame.eotf =
1021 pParams->hdrInfoFrame.eotf;
1022 pFlipState->hdrInfoFrame.staticMetadata =
1023 pParams->hdrInfoFrame.staticMetadata;
1024 }
1025 pFlipState->hdrInfoFrame.enabled =
1026 pParams->hdrInfoFrame.enabled;
1027 }
1028
1029 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1030 if (layer == NVKMS_MAIN_LAYER) {
1031 if (!UpdateMainLayerFlipEvoHwState(pOpenDev, pDevEvo, sd, head,
1032 pParams, pFlipState, allowVrr)) {
1033 return FALSE;
1034 }
1035 continue;
1036 }
1037
1038 if (!UpdateOverlayLayerFlipEvoHwState(pOpenDev, pDevEvo, sd, head,
1039 layer, pParams, pFlipState)) {
1040 return FALSE;
1041 }
1042 }
1043
1044 if (!AssignUsageBounds(pDevEvo, head, pFlipState)) {
1045 return FALSE;
1046 }
1047
1048 /*
1049 * If there is active cursor/cropped-window(overlay) without full screen
1050 * window(base/core) then NVKMS is supposed to disable MidFrame/DWCF
1051 * watermark.
1052 */
1053
1054 pFlipState->disableMidFrameAndDWCFWatermark = FALSE;
1055
1056 if (NV5070_CTRL_SYSTEM_GET_CAP(
1057 pDevEvo->capsBits,
1058 NV5070_CTRL_SYSTEM_CAPS_BUG_2052012_GLITCHY_MCLK_SWITCH) &&
1059 !pFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT]) {
1060
1061 if (pFlipState->cursor.pSurfaceEvo != NULL) {
1062 pFlipState->disableMidFrameAndDWCFWatermark = TRUE;
1063 } else {
1064 NvU32 layer;
1065
1066 /*
1067 * XXX TODO: Check the output size of the overlay in order
1068 * to determine if it will be fullscreen or not.
1069 */
1070 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1071 if (layer != NVKMS_MAIN_LAYER &&
1072 pFlipState->layer[layer].pSurfaceEvo[NVKMS_LEFT] != NULL) {
1073 pFlipState->disableMidFrameAndDWCFWatermark = TRUE;
1074 break;
1075 }
1076 }
1077 }
1078 }
1079
1080 return TRUE;
1081 }
1082
1083 /*
1084 * Checks that if the surface is NULL (i.e. no image will be shown), various
1085 * other elements must be NULL as well. If the surface is not NULL, verifies
1086 * that the sizeIn/Out have nonzero values.
1087 */
ValidateFlipChannelEvoHwState(const NVFlipChannelEvoHwState * pState)1088 inline static NvBool ValidateFlipChannelEvoHwState(
1089 const NVFlipChannelEvoHwState *pState)
1090 {
1091 if (pState->pSurfaceEvo[NVKMS_LEFT] != NULL) {
1092 /* Verify sizes are valid. */
1093 if ((pState->sizeIn.width == 0) || (pState->sizeIn.height == 0) ||
1094 (pState->sizeOut.width == 0) || (pState->sizeOut.height == 0)) {
1095 return FALSE;
1096 }
1097
1098 return TRUE;
1099 }
1100
1101 if (pState->completionNotifier.surface.pSurfaceEvo != NULL) {
1102 return FALSE;
1103 }
1104
1105 if (!pState->syncObject.usingSyncpt) {
1106 if (pState->syncObject.u.semaphores.acquireSurface.pSurfaceEvo != NULL) {
1107 return FALSE;
1108 }
1109
1110 if (pState->syncObject.u.semaphores.releaseSurface.pSurfaceEvo != NULL) {
1111 return FALSE;
1112 }
1113 }
1114
1115 return TRUE;
1116 }
1117
ValidateSurfaceSize(const NVDevEvoRec * pDevEvo,const NVSurfaceEvoRec * pSurfaceEvo,const struct NvKmsRect * sourceFetchRect)1118 static NvBool ValidateSurfaceSize(
1119 const NVDevEvoRec *pDevEvo,
1120 const NVSurfaceEvoRec *pSurfaceEvo,
1121 const struct NvKmsRect *sourceFetchRect)
1122 {
1123 NvU8 planeIndex;
1124
1125 if ((pSurfaceEvo->widthInPixels > pDevEvo->caps.maxWidthInPixels) ||
1126 (pSurfaceEvo->heightInPixels > pDevEvo->caps.maxHeight)) {
1127 return FALSE;
1128 }
1129
1130 FOR_ALL_VALID_PLANES(planeIndex, pSurfaceEvo) {
1131
1132 NvU64 planePitch = pSurfaceEvo->planes[planeIndex].pitch;
1133
1134 /*
1135 * Convert planePitch to units of bytes if it's currently specified in
1136 * units of blocks. Each block is 64-bytes wide.
1137 */
1138 if (pSurfaceEvo->layout == NvKmsSurfaceMemoryLayoutBlockLinear) {
1139 planePitch <<= NVKMS_BLOCK_LINEAR_LOG_GOB_WIDTH;
1140 }
1141
1142 if (planePitch > pDevEvo->caps.maxWidthInBytes) {
1143 return FALSE;
1144 }
1145 }
1146
1147 if (!pDevEvo->hal->ValidateWindowFormat(pSurfaceEvo->format,
1148 sourceFetchRect,
1149 NULL)) {
1150 return FALSE;
1151 }
1152
1153 return TRUE;
1154 }
1155
1156 static NvBool
ValidateMainFlipChannelEvoHwState(const NVDevEvoRec * pDevEvo,const NVFlipChannelEvoHwState * pHwState,const NVHwModeTimingsEvo * pTimings,struct NvKmsPoint viewPortPointIn)1157 ValidateMainFlipChannelEvoHwState(const NVDevEvoRec *pDevEvo,
1158 const NVFlipChannelEvoHwState *pHwState,
1159 const NVHwModeTimingsEvo *pTimings,
1160 struct NvKmsPoint viewPortPointIn)
1161 {
1162 NvU32 eye;
1163 const NVSurfaceEvoRec *pFirstSurfaceEvo = NULL;
1164
1165 /*
1166 * This struct represents the source fetch rectangle for a given surface,
1167 * and will be populated later as such. This function doesn't explicitly set
1168 * sourceFetchRect.{x,y} because NVKMS currently doesn't support programming
1169 * source fetch offsets, so the init value of 0 should be fine for both of
1170 * these fields.
1171 */
1172 struct NvKmsRect sourceFetchRect = {0};
1173
1174 if (!ValidateFlipChannelEvoHwState(pHwState)) {
1175 return FALSE;
1176 }
1177
1178 for (eye = 0; eye < NVKMS_MAX_EYES; eye++) {
1179 const NVSurfaceEvoRec *pSurfaceEvo = pHwState->pSurfaceEvo[eye];
1180
1181 if (pSurfaceEvo == NULL) {
1182 continue;
1183 }
1184
1185 if (pFirstSurfaceEvo == NULL) {
1186 pFirstSurfaceEvo = pSurfaceEvo;
1187 } else if (pSurfaceEvo->widthInPixels !=
1188 pFirstSurfaceEvo->widthInPixels ||
1189 pSurfaceEvo->heightInPixels !=
1190 pFirstSurfaceEvo->heightInPixels) {
1191 return FALSE;
1192 }
1193
1194 sourceFetchRect.width = pHwState->sizeIn.width;
1195 sourceFetchRect.height = pHwState->sizeIn.height;
1196
1197 if (!ValidateSurfaceSize(pDevEvo, pSurfaceEvo, &sourceFetchRect)) {
1198 return FALSE;
1199 }
1200
1201 /* The use of A_plus_B_greater_than_C_U16 is only valid if these
1202 * fit in a U16 */
1203 nvAssert(pSurfaceEvo->widthInPixels <= NV_U16_MAX);
1204 nvAssert(pSurfaceEvo->heightInPixels <= NV_U16_MAX);
1205 /* And the checks above in ValidateSurfaceSize should have
1206 * guaranteed that. */
1207 nvAssert(pDevEvo->caps.maxWidthInPixels <= NV_U16_MAX);
1208 nvAssert(pDevEvo->caps.maxHeight <= NV_U16_MAX);
1209
1210 /*
1211 * Validate that the requested viewport parameters fit within the
1212 * specified surface, unless the main layer is allowed to be smaller
1213 * than the viewport.
1214 */
1215 if (!pDevEvo->caps.layerCaps[NVKMS_MAIN_LAYER].supportsWindowMode) {
1216 if (A_plus_B_greater_than_C_U16(viewPortPointIn.x,
1217 pTimings->viewPort.in.width,
1218 pSurfaceEvo->widthInPixels)) {
1219 return FALSE;
1220 }
1221
1222 if (A_plus_B_greater_than_C_U16(viewPortPointIn.y,
1223 pTimings->viewPort.in.height,
1224 pSurfaceEvo->heightInPixels)) {
1225 return FALSE;
1226 }
1227 }
1228 }
1229
1230 return TRUE;
1231 }
1232
1233 static NvBool
ValidateOverlayFlipChannelEvoHwState(const NVDevEvoRec * pDevEvo,const NVFlipChannelEvoHwState * pHwState)1234 ValidateOverlayFlipChannelEvoHwState(const NVDevEvoRec *pDevEvo,
1235 const NVFlipChannelEvoHwState *pHwState)
1236 {
1237 const NVSurfaceEvoRec *pSurfaceEvo = pHwState->pSurfaceEvo[NVKMS_LEFT];
1238
1239 /*
1240 * This struct represents the source fetch rectangle for a given surface,
1241 * and will be populated later as such. This function doesn't explicitly set
1242 * sourceFetchRect.{x,y} because NVKMS currently doesn't support programming
1243 * source fetch offsets, so the init value of 0 should be fine for both of
1244 * these fields.
1245 */
1246 struct NvKmsRect sourceFetchRect = {0};
1247
1248 if (!ValidateFlipChannelEvoHwState(pHwState)) {
1249 return FALSE;
1250 }
1251
1252 if (pSurfaceEvo == NULL) {
1253 return TRUE;
1254 }
1255
1256 sourceFetchRect.width = pHwState->sizeIn.width;
1257 sourceFetchRect.height = pHwState->sizeIn.height;
1258
1259 if (!ValidateSurfaceSize(pDevEvo, pSurfaceEvo, &sourceFetchRect)) {
1260 return FALSE;
1261 }
1262
1263 /* Validate input size against surface size. */
1264 if (pHwState->sizeIn.width > pSurfaceEvo->widthInPixels ||
1265 pHwState->sizeIn.height > pSurfaceEvo->heightInPixels) {
1266 return FALSE;
1267 }
1268
1269 return TRUE;
1270 }
1271
1272 static NvBool
ValidateHDR(const NVDevEvoRec * pDevEvo,const NvU32 head,const NVFlipEvoHwState * pFlipState)1273 ValidateHDR(const NVDevEvoRec *pDevEvo,
1274 const NvU32 head,
1275 const NVFlipEvoHwState *pFlipState)
1276 {
1277 NvU32 layerStaticMetadataCount = 0;
1278 NvU32 layerSupportedCount = 0;
1279
1280 NvU32 layer;
1281
1282 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1283 if (pDevEvo->caps.layerCaps[layer].supportsHDR) {
1284 layerSupportedCount++;
1285 }
1286
1287 if (pFlipState->layer[layer].hdrStaticMetadata.enabled) {
1288 layerStaticMetadataCount++;
1289
1290 /*
1291 * If HDR static metadata is enabled, we may need TMO. CSC11 will be
1292 * used by NVKMS to convert from linear FP16 LMS to linear FP16 RGB.
1293 * As such, the user-supplied precomp CSC can't be programmed into
1294 * CSC11 in this case.
1295 */
1296 if (!nvIsCscMatrixIdentity(&pFlipState->layer[layer].cscMatrix)) {
1297 return FALSE;
1298 }
1299
1300 // Already checked in UpdateLayerFlipEvoHwStateHDRStaticMetadata()
1301 nvAssert(pDevEvo->caps.layerCaps[layer].supportsHDR);
1302 }
1303 }
1304
1305 // If enabling HDR TF...
1306 // XXX HDR TODO: Handle other transfer functions
1307 if (pFlipState->tf == NVKMS_OUTPUT_TF_PQ) {
1308 // At least one layer must support HDR.
1309 if (layerSupportedCount == 0) {
1310 return FALSE;
1311 }
1312
1313 // If HDR metadata is not overridden for the head...
1314 if (!pFlipState->hdrInfoFrame.enabled) {
1315 // At least one layer must have static metadata.
1316 if (layerStaticMetadataCount == 0) {
1317 return FALSE;
1318 }
1319 }
1320 }
1321
1322 // Only one layer can specify HDR static metadata.
1323 // XXX HDR TODO: Support multiple layers with HDR static metadata
1324 if (layerStaticMetadataCount > 1) {
1325 return FALSE;
1326 }
1327
1328 return TRUE;
1329 }
1330
1331 static NvBool
ValidateColorspace(const NVDevEvoRec * pDevEvo,const NvU32 head,const NVFlipEvoHwState * pFlipState)1332 ValidateColorspace(const NVDevEvoRec *pDevEvo,
1333 const NvU32 head,
1334 const NVFlipEvoHwState *pFlipState)
1335 {
1336 NvU32 layer;
1337
1338 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1339 if ((pFlipState->layer[layer].colorSpace !=
1340 NVKMS_INPUT_COLORSPACE_NONE)) {
1341
1342 NVSurfaceEvoPtr pSurfaceEvo =
1343 pFlipState->layer[layer].pSurfaceEvo[NVKMS_LEFT];
1344 const NvKmsSurfaceMemoryFormatInfo *pFormatInfo =
1345 (pSurfaceEvo != NULL) ?
1346 nvKmsGetSurfaceMemoryFormatInfo(pSurfaceEvo->format) : NULL;
1347
1348 // XXX HDR TODO: Support YUV.
1349 if ((pFormatInfo == NULL) || pFormatInfo->isYUV) {
1350 return FALSE;
1351 }
1352
1353 // FP16 is only for use with scRGB.
1354 if ((pFlipState->layer[layer].colorSpace !=
1355 NVKMS_INPUT_COLORSPACE_SCRGB_LINEAR) &&
1356 ((pSurfaceEvo->format ==
1357 NvKmsSurfaceMemoryFormatRF16GF16BF16AF16) ||
1358 (pSurfaceEvo->format ==
1359 NvKmsSurfaceMemoryFormatRF16GF16BF16XF16))) {
1360 return FALSE;
1361 }
1362
1363 // scRGB is only compatible with FP16.
1364 if ((pFlipState->layer[layer].colorSpace ==
1365 NVKMS_INPUT_COLORSPACE_SCRGB_LINEAR) &&
1366 !((pSurfaceEvo->format ==
1367 NvKmsSurfaceMemoryFormatRF16GF16BF16AF16) ||
1368 (pSurfaceEvo->format ==
1369 NvKmsSurfaceMemoryFormatRF16GF16BF16XF16))) {
1370 return FALSE;
1371 }
1372 }
1373 }
1374
1375 return TRUE;
1376 }
1377
ValidateCompositionDepth(const NVFlipEvoHwState * pFlipState,const NvU32 layer)1378 static NvU32 ValidateCompositionDepth(const NVFlipEvoHwState *pFlipState,
1379 const NvU32 layer)
1380 {
1381 NvU32 tmpLayer;
1382
1383 if (pFlipState->layer[layer].pSurfaceEvo[NVKMS_LEFT] == NULL) {
1384 return TRUE;
1385 }
1386
1387 /* Depth should be different for each of the layers owned by the head */
1388 for (tmpLayer = 0; tmpLayer < ARRAY_LEN(pFlipState->layer); tmpLayer++) {
1389 if (pFlipState->layer[tmpLayer].pSurfaceEvo[NVKMS_LEFT] == NULL) {
1390 continue;
1391 }
1392
1393 if ((tmpLayer != layer) &&
1394 (pFlipState->layer[tmpLayer].composition.depth ==
1395 pFlipState->layer[layer].composition.depth)) {
1396 return FALSE;
1397 }
1398 }
1399
1400 /* Depth of the main layer should be the greatest one */
1401 if (pFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT] != NULL) {
1402 if (pFlipState->layer[NVKMS_MAIN_LAYER].composition.depth <
1403 pFlipState->layer[layer].composition.depth) {
1404 return FALSE;
1405 }
1406 }
1407
1408 return TRUE;
1409 }
1410
1411 /*!
1412 * Perform validation of the the given NVFlipEvoHwState.
1413 */
nvValidateFlipEvoHwState(const NVDevEvoRec * pDevEvo,const NvU32 head,const NVHwModeTimingsEvo * pTimings,const NVFlipEvoHwState * pFlipState)1414 NvBool nvValidateFlipEvoHwState(
1415 const NVDevEvoRec *pDevEvo,
1416 const NvU32 head,
1417 const NVHwModeTimingsEvo *pTimings,
1418 const NVFlipEvoHwState *pFlipState)
1419 {
1420 NvU32 layer;
1421
1422 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1423 if (!ValidateCompositionDepth(pFlipState, layer)) {
1424 return FALSE;
1425 }
1426
1427 if (layer == NVKMS_MAIN_LAYER) {
1428 if (!ValidateMainFlipChannelEvoHwState(pDevEvo,
1429 &pFlipState->layer[layer],
1430 pTimings,
1431 pFlipState->viewPortPointIn)) {
1432 return FALSE;
1433 }
1434 } else {
1435 const NVFlipChannelEvoHwState *pMainLayerState =
1436 &pFlipState->layer[NVKMS_MAIN_LAYER];
1437
1438 /*
1439 * No overlay layer should be enabled if the main
1440 * layer is disabled.
1441 */
1442 if ((pMainLayerState->pSurfaceEvo[NVKMS_LEFT] == NULL) &&
1443 (pFlipState->layer[layer].pSurfaceEvo[NVKMS_LEFT] != NULL)) {
1444 return FALSE;
1445 }
1446
1447 if (!pFlipState->dirty.layer[layer]) {
1448 continue;
1449 }
1450
1451 if (!ValidateOverlayFlipChannelEvoHwState(pDevEvo,
1452 &pFlipState->layer[layer])) {
1453 return FALSE;
1454 }
1455 }
1456 }
1457
1458 if (!ValidateHDR(pDevEvo, head, pFlipState)) {
1459 return FALSE;
1460 }
1461
1462 if (!ValidateColorspace(pDevEvo, head, pFlipState)) {
1463 return FALSE;
1464 }
1465
1466 /* XXX NVKMS TODO: validate cursor x,y against current viewport in? */
1467
1468 return ValidateUsageBounds(pDevEvo,
1469 head,
1470 &pFlipState->usage,
1471 &pTimings->viewPort.possibleUsage);
1472 }
1473
1474 /*
1475 * Record in the updateState that the given channel needs interlocked
1476 * window immediate updates.
1477 */
UpdateWinImmInterlockState(NVDevEvoPtr pDevEvo,NVEvoUpdateState * updateState,const NVEvoChannel * pChannel)1478 static void UpdateWinImmInterlockState(NVDevEvoPtr pDevEvo,
1479 NVEvoUpdateState *updateState,
1480 const NVEvoChannel *pChannel)
1481 {
1482 const NvU32 subDevMask = nvPeekEvoSubDevMask(pDevEvo);
1483 NvU32 sd;
1484
1485 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
1486 if (subDevMask & (1 << sd)) {
1487 updateState->subdev[sd].winImmInterlockMask |=
1488 pChannel->channelMask;
1489 }
1490 }
1491 }
1492
1493 /*!
1494 * Record in the updateState that the given channel's method are eligible for
1495 * flip locking.
1496 */
UpdateUpdateFlipLockState(NVDevEvoPtr pDevEvo,NVEvoUpdateState * updateState,const NVEvoChannel * pChannel)1497 static void UpdateUpdateFlipLockState(NVDevEvoPtr pDevEvo,
1498 NVEvoUpdateState *updateState,
1499 const NVEvoChannel *pChannel)
1500 {
1501 const NvU32 subDevMask = nvPeekEvoSubDevMask(pDevEvo);
1502 NvU32 sd;
1503
1504 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
1505 if (subDevMask & (1 << sd)) {
1506 updateState->subdev[sd].flipLockQualifyingMask |=
1507 pChannel->channelMask;
1508 }
1509 }
1510 }
1511
1512 // Adjust from EDID-encoded maxCLL/maxFALL to actual values in units of 1 cd/m2
MaxCvToVal(NvU32 cv)1513 static inline NvU32 MaxCvToVal(NvU32 cv)
1514 {
1515 if (cv == 0) {
1516 return 0;
1517 }
1518
1519 // 50*2^(cv/32)
1520 return f64_to_ui32(
1521 f64_mul(ui32_to_f64(50),
1522 nvKmsPow(ui32_to_f64(2),
1523 f64_div(ui32_to_f64(cv),
1524 ui32_to_f64(32)))), softfloat_round_near_even, FALSE);
1525 }
1526
1527 // Adjust from EDID-encoded minCLL to actual value in units of 0.0001 cd/m2
MinCvToVal(NvU32 cv,NvU32 maxCLL)1528 static inline NvU32 MinCvToVal(NvU32 cv, NvU32 maxCLL)
1529 {
1530 // 10,000 * (minCLL = (maxCLL * ((cv/255)^2 / 100)))
1531 return f64_to_ui32(
1532 f64_mul(ui32_to_f64(10000),
1533 f64_mul(ui32_to_f64(maxCLL),
1534 f64_div(nvKmsPow(f64_div(ui32_to_f64(cv),
1535 ui32_to_f64(255)),
1536 ui32_to_f64(2)),
1537 ui32_to_f64(100)))),
1538 softfloat_round_near_even, FALSE);
1539 }
1540
UpdateHDR(NVDevEvoPtr pDevEvo,const NVFlipEvoHwState * pFlipState,const NvU32 sd,const NvU32 head,const NVT_HDR_STATIC_METADATA * pHdrInfo,NVEvoUpdateState * updateState)1541 static void UpdateHDR(NVDevEvoPtr pDevEvo,
1542 const NVFlipEvoHwState *pFlipState,
1543 const NvU32 sd,
1544 const NvU32 head,
1545 const NVT_HDR_STATIC_METADATA *pHdrInfo,
1546 NVEvoUpdateState *updateState)
1547 {
1548 NVDispEvoPtr pDispEvo = pDevEvo->gpus[sd].pDispEvo;
1549 NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
1550 NvBool dirty = FALSE;
1551
1552 if (pFlipState->dirty.tf) {
1553 pHeadState->tf = pFlipState->tf;
1554
1555 dirty = TRUE;
1556 }
1557
1558 if (pFlipState->dirty.hdrStaticMetadata) {
1559 NvBool found = FALSE;
1560
1561 /*
1562 * Track if HDR static metadata is overridden for the head in order to
1563 * initialize subsequent instances of NVFlipEvoHwState.
1564 */
1565 pHeadState->hdrInfoFrameOverride.enabled =
1566 pFlipState->hdrInfoFrame.enabled;
1567 pHeadState->hdrInfoFrameOverride.eotf =
1568 pFlipState->hdrInfoFrame.eotf;
1569 pHeadState->hdrInfoFrameOverride.staticMetadata =
1570 pFlipState->hdrInfoFrame.staticMetadata;
1571
1572 // Populate head with updated static metadata.
1573
1574 if (pFlipState->hdrInfoFrame.enabled) {
1575 // If HDR static metadata is overridden for the head, use that.
1576 pHeadState->hdrInfoFrame.staticMetadata =
1577 pFlipState->hdrInfoFrame.staticMetadata;
1578 pHeadState->hdrInfoFrame.eotf =
1579 pFlipState->hdrInfoFrame.eotf;
1580
1581 pHeadState->hdrInfoFrame.state = NVKMS_HDR_INFOFRAME_STATE_ENABLED;
1582 found = TRUE;
1583 } else {
1584 NvU32 layer;
1585
1586 /*
1587 * If HDR static metadata is specified for layer(s), construct the
1588 * head's HDR static metadata using those.
1589 */
1590 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1591 if (pFlipState->layer[layer].hdrStaticMetadata.enabled) {
1592 NvU32 targetMaxCLL = MaxCvToVal(pHdrInfo->max_cll);
1593
1594 /*
1595 * Only one layer can currently specify static metadata,
1596 * verified by ValidateHDR().
1597 *
1598 * XXX HDR TODO: Combine metadata from multiple layers.
1599 */
1600 nvAssert(!found);
1601
1602 // Send this layer's metadata to the display.
1603 pHeadState->hdrInfoFrame.staticMetadata =
1604 pFlipState->layer[layer].hdrStaticMetadata.val;
1605
1606 // Infer metadata eotf from output tf
1607 // XXX HDR TODO: Handle other transfer functions
1608 switch (pHeadState->tf) {
1609 default:
1610 nvAssert(!"Unrecognized output TF");
1611 // Fall through
1612 case NVKMS_OUTPUT_TF_TRADITIONAL_GAMMA_SDR:
1613 case NVKMS_OUTPUT_TF_NONE:
1614 pHeadState->hdrInfoFrame.eotf =
1615 NVKMS_INFOFRAME_EOTF_SDR_GAMMA;
1616 break;
1617 case NVKMS_OUTPUT_TF_PQ:
1618 pHeadState->hdrInfoFrame.eotf =
1619 NVKMS_INFOFRAME_EOTF_ST2084;
1620 break;
1621 }
1622
1623 pHeadState->hdrInfoFrame.state =
1624 NVKMS_HDR_INFOFRAME_STATE_ENABLED;
1625 found = TRUE;
1626
1627 /*
1628 * Prepare for tone mapping. If we expect to tone map and
1629 * the EDID has valid lum values, mirror EDID lum values to
1630 * prevent redundant tone mapping by the display. We will
1631 * tone map to the specified maxCLL.
1632 */
1633 if (nvNeedsTmoLut(pDevEvo, pDevEvo->head[head].layer[layer],
1634 &pFlipState->layer[layer],
1635 nvGetHDRSrcMaxLum(
1636 &pFlipState->layer[layer]),
1637 targetMaxCLL)) {
1638 NvU32 targetMaxFALL = MaxCvToVal(pHdrInfo->max_fall);
1639 if ((targetMaxCLL > 0) &&
1640 (targetMaxCLL <= 10000) &&
1641 (targetMaxCLL >= targetMaxFALL)) {
1642
1643 NvU32 targetMinCLL = MinCvToVal(pHdrInfo->min_cll,
1644 targetMaxCLL);
1645
1646 pHeadState->hdrInfoFrame.staticMetadata.
1647 maxDisplayMasteringLuminance = targetMaxCLL;
1648 pHeadState->hdrInfoFrame.staticMetadata.
1649 minDisplayMasteringLuminance = targetMinCLL;
1650 pHeadState->hdrInfoFrame.staticMetadata.maxCLL =
1651 targetMaxCLL;
1652 pHeadState->hdrInfoFrame.staticMetadata.maxFALL =
1653 targetMaxFALL;
1654 }
1655 }
1656 }
1657 }
1658 }
1659
1660 if (!found) {
1661 nvkms_memset(&pHeadState->hdrInfoFrame.staticMetadata, 0,
1662 sizeof(struct NvKmsHDRStaticMetadata));
1663 if (pHeadState->hdrInfoFrame.state ==
1664 NVKMS_HDR_INFOFRAME_STATE_ENABLED) {
1665 pHeadState->hdrInfoFrame.state =
1666 NVKMS_HDR_INFOFRAME_STATE_TRANSITIONING;
1667 }
1668 }
1669
1670 dirty = TRUE;
1671 }
1672
1673 if (pFlipState->dirty.colorimetry) {
1674 pHeadState->colorimetry = pFlipState->colorimetry;
1675 dirty = TRUE;
1676 }
1677
1678 if (dirty) {
1679 // Update OCSC / OLUT
1680 nvEvoSetLUTContextDma(pDispEvo, head, updateState);
1681 }
1682 }
1683
1684 /*!
1685 * Program a flip on all requested layers on the specified head.
1686 *
1687 * This also updates pDispEvo->headState[head], caching what was programmed.
1688
1689 * \param[in,out] pDispEvo The disp on which the flip should be performed.
1690 * \param[in] head The head on which the flip should be performed.
1691 * \param[in] pFlipState The description of how to update each layer.
1692 * \param[in,out] updateState Indicates which channels require UPDATEs
1693 */
nvFlipEvoOneHead(NVDevEvoPtr pDevEvo,const NvU32 sd,const NvU32 head,const NVT_HDR_STATIC_METADATA * pHdrInfo,const NVFlipEvoHwState * pFlipState,NvBool allowFlipLock,NVEvoUpdateState * updateState)1694 void nvFlipEvoOneHead(
1695 NVDevEvoPtr pDevEvo,
1696 const NvU32 sd,
1697 const NvU32 head,
1698 const NVT_HDR_STATIC_METADATA *pHdrInfo,
1699 const NVFlipEvoHwState *pFlipState,
1700 NvBool allowFlipLock,
1701 NVEvoUpdateState *updateState)
1702 {
1703 const NvU32 subDeviceMask = NVBIT(sd);
1704 const NVDispHeadStateEvoRec *pHeadState =
1705 &pDevEvo->gpus[sd].pDispEvo->headState[head];
1706 NvBool bypassComposition = pHeadState->bypassComposition;
1707 NVEvoSubDevHeadStateRec *pSdHeadState =
1708 &pDevEvo->gpus[sd].headState[head];
1709 NvU32 layer;
1710
1711 /*
1712 * Provide the pre-update hardware state (in pSdHeadState) and the new
1713 * target state (pFlipState) to the HAL implementation so that it has the
1714 * information it needs to implement the workaround for hardware bug
1715 * 2193096, which requires special logic on transitions between NULL and
1716 * non-NULL ctxdmas (and vice versa).
1717 */
1718 pDevEvo->hal->FlipTransitionWAR(pDevEvo, sd, head,
1719 pSdHeadState, pFlipState,
1720 updateState);
1721
1722 /*
1723 * Promote the software state first, such that the hardware programming
1724 * paths below see the new state atomically.
1725 */
1726 if (pFlipState->dirty.viewPortPointIn) {
1727 pSdHeadState->viewPortPointIn = pFlipState->viewPortPointIn;
1728 }
1729
1730 if (pFlipState->dirty.cursorSurface || pFlipState->dirty.cursorPosition) {
1731 pSdHeadState->cursor = pFlipState->cursor;
1732 }
1733
1734 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1735 if (pFlipState->dirty.layer[layer]) {
1736 pSdHeadState->layer[layer] = pFlipState->layer[layer];
1737 }
1738 }
1739
1740 if (pFlipState->dirty.viewPortPointIn) {
1741 nvSetViewPortPointInEvo(pDevEvo->gpus[sd].pDispEvo,
1742 head,
1743 pFlipState->viewPortPointIn.x,
1744 pFlipState->viewPortPointIn.y,
1745 updateState);
1746 }
1747
1748 if (pFlipState->dirty.cursorSurface) {
1749 nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
1750 pDevEvo->hal->SetCursorImage(pDevEvo,
1751 head,
1752 pSdHeadState->cursor.pSurfaceEvo,
1753 updateState,
1754 &pSdHeadState->cursor.cursorCompParams);
1755 nvPopEvoSubDevMask(pDevEvo);
1756 }
1757
1758 if (pFlipState->dirty.cursorPosition) {
1759 nvEvoMoveCursorInternal(pDevEvo->gpus[sd].pDispEvo,
1760 head,
1761 pFlipState->cursor.x,
1762 pFlipState->cursor.y);
1763 }
1764
1765 UpdateHDR(pDevEvo, pFlipState, sd, head, pHdrInfo, updateState);
1766
1767 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
1768 if (!pFlipState->dirty.layer[layer]) {
1769 continue;
1770 }
1771
1772 nvPushEvoSubDevMask(pDevEvo, subDeviceMask);
1773
1774 if (pFlipState->dirty.layerPosition[layer]) {
1775 /* Ensure position updates are supported on this layer. */
1776 nvAssert(pDevEvo->caps.layerCaps[layer].supportsWindowMode);
1777
1778 pDevEvo->hal->SetImmPointOut(pDevEvo,
1779 pDevEvo->head[head].layer[layer],
1780 sd,
1781 updateState,
1782 pFlipState->layer[layer].outputPosition.x,
1783 pFlipState->layer[layer].outputPosition.y);
1784
1785 if (pDevEvo->hal->caps.supportsSynchronizedOverlayPositionUpdate) {
1786 UpdateWinImmInterlockState(pDevEvo, updateState,
1787 pDevEvo->head[head].layer[layer]);
1788 }
1789 }
1790
1791 /* Inform DIFR about the upcoming flip. */
1792 if (pDevEvo->pDifrState) {
1793 nvDIFRNotifyFlip(pDevEvo->pDifrState);
1794 }
1795
1796 pDevEvo->hal->Flip(pDevEvo,
1797 pDevEvo->head[head].layer[layer],
1798 &pFlipState->layer[layer],
1799 updateState,
1800 bypassComposition);
1801 if (layer == NVKMS_MAIN_LAYER && allowFlipLock) {
1802 UpdateUpdateFlipLockState(pDevEvo, updateState,
1803 pDevEvo->head[head].layer[layer]);
1804 }
1805 nvPopEvoSubDevMask(pDevEvo);
1806 }
1807
1808 pSdHeadState->targetUsage = pFlipState->usage;
1809
1810 pSdHeadState->targetDisableMidFrameAndDWCFWatermark =
1811 pFlipState->disableMidFrameAndDWCFWatermark;
1812 }
1813
ChangeSurfaceFlipRefCount(NVDevEvoPtr pDevEvo,NVSurfaceEvoPtr pSurfaceEvo,NvBool increase)1814 static void ChangeSurfaceFlipRefCount(
1815 NVDevEvoPtr pDevEvo,
1816 NVSurfaceEvoPtr pSurfaceEvo,
1817 NvBool increase)
1818 {
1819 if (pSurfaceEvo != NULL) {
1820 if (increase) {
1821 nvEvoIncrementSurfaceRefCnts(pSurfaceEvo);
1822 } else {
1823 nvEvoDecrementSurfaceRefCnts(pDevEvo, pSurfaceEvo);
1824 }
1825 }
1826 }
1827
nvUpdateSurfacesFlipRefCount(NVDevEvoPtr pDevEvo,const NvU32 head,NVFlipEvoHwState * pFlipState,NvBool increase)1828 void nvUpdateSurfacesFlipRefCount(
1829 NVDevEvoPtr pDevEvo,
1830 const NvU32 head,
1831 NVFlipEvoHwState *pFlipState,
1832 NvBool increase)
1833 {
1834 NvU32 i;
1835
1836 ChangeSurfaceFlipRefCount(
1837 pDevEvo,
1838 pFlipState->cursor.pSurfaceEvo,
1839 increase);
1840
1841 for (i = 0; i < pDevEvo->head[head].numLayers; i++) {
1842 NVFlipChannelEvoHwState *pLayerFlipState = &pFlipState->layer[i];
1843
1844 ChangeSurfaceFlipRefCount(
1845 pDevEvo,
1846 pLayerFlipState->pSurfaceEvo[NVKMS_LEFT],
1847 increase);
1848 ChangeSurfaceFlipRefCount(
1849 pDevEvo,
1850 pLayerFlipState->pSurfaceEvo[NVKMS_RIGHT],
1851 increase);
1852 ChangeSurfaceFlipRefCount(
1853 pDevEvo,
1854 pLayerFlipState->completionNotifier.surface.pSurfaceEvo,
1855 increase);
1856
1857 if (!pLayerFlipState->syncObject.usingSyncpt) {
1858 ChangeSurfaceFlipRefCount(
1859 pDevEvo,
1860 pLayerFlipState->syncObject.u.semaphores.acquireSurface.pSurfaceEvo,
1861 increase);
1862 ChangeSurfaceFlipRefCount(
1863 pDevEvo,
1864 pLayerFlipState->syncObject.u.semaphores.releaseSurface.pSurfaceEvo,
1865 increase);
1866 }
1867 }
1868 }
1869
UnionScalingUsageBounds(const struct NvKmsScalingUsageBounds * a,const struct NvKmsScalingUsageBounds * b,struct NvKmsScalingUsageBounds * ret)1870 static void UnionScalingUsageBounds(
1871 const struct NvKmsScalingUsageBounds *a,
1872 const struct NvKmsScalingUsageBounds *b,
1873 struct NvKmsScalingUsageBounds *ret)
1874 {
1875 ret->maxVDownscaleFactor = NV_MAX(a->maxVDownscaleFactor,
1876 b->maxVDownscaleFactor);
1877 ret->maxHDownscaleFactor = NV_MAX(a->maxHDownscaleFactor,
1878 b->maxHDownscaleFactor);
1879 ret->vTaps = NV_MAX(a->vTaps, b->vTaps);
1880 ret->vUpscalingAllowed = a->vUpscalingAllowed || b->vUpscalingAllowed;
1881 }
1882
nvUnionUsageBounds(const struct NvKmsUsageBounds * a,const struct NvKmsUsageBounds * b,struct NvKmsUsageBounds * ret)1883 void nvUnionUsageBounds(const struct NvKmsUsageBounds *a,
1884 const struct NvKmsUsageBounds *b,
1885 struct NvKmsUsageBounds *ret)
1886 {
1887 NvU32 i;
1888
1889 nvkms_memset(ret, 0, sizeof(*ret));
1890
1891 for (i = 0; i < ARRAY_LEN(a->layer); i++) {
1892 nvAssert(a->layer[i].usable ==
1893 !!a->layer[i].supportedSurfaceMemoryFormats);
1894 nvAssert(b->layer[i].usable ==
1895 !!b->layer[i].supportedSurfaceMemoryFormats);
1896
1897 ret->layer[i].usable = a->layer[i].usable || b->layer[i].usable;
1898
1899 ret->layer[i].supportedSurfaceMemoryFormats =
1900 a->layer[i].supportedSurfaceMemoryFormats |
1901 b->layer[i].supportedSurfaceMemoryFormats;
1902
1903 UnionScalingUsageBounds(&a->layer[i].scaling,
1904 &b->layer[i].scaling,
1905 &ret->layer[i].scaling);
1906 }
1907 }
1908
IntersectScalingUsageBounds(const struct NvKmsScalingUsageBounds * a,const struct NvKmsScalingUsageBounds * b,struct NvKmsScalingUsageBounds * ret)1909 static void IntersectScalingUsageBounds(
1910 const struct NvKmsScalingUsageBounds *a,
1911 const struct NvKmsScalingUsageBounds *b,
1912 struct NvKmsScalingUsageBounds *ret)
1913 {
1914 ret->maxVDownscaleFactor = NV_MIN(a->maxVDownscaleFactor,
1915 b->maxVDownscaleFactor);
1916 ret->maxHDownscaleFactor = NV_MIN(a->maxHDownscaleFactor,
1917 b->maxHDownscaleFactor);
1918 ret->vTaps = NV_MIN(a->vTaps, b->vTaps);
1919 ret->vUpscalingAllowed = a->vUpscalingAllowed && b->vUpscalingAllowed;
1920 }
1921
nvIntersectUsageBounds(const struct NvKmsUsageBounds * a,const struct NvKmsUsageBounds * b,struct NvKmsUsageBounds * ret)1922 void nvIntersectUsageBounds(const struct NvKmsUsageBounds *a,
1923 const struct NvKmsUsageBounds *b,
1924 struct NvKmsUsageBounds *ret)
1925 {
1926 NvU32 i;
1927
1928 nvkms_memset(ret, 0, sizeof(*ret));
1929
1930 for (i = 0; i < ARRAY_LEN(a->layer); i++) {
1931 nvAssert(a->layer[i].usable ==
1932 !!a->layer[i].supportedSurfaceMemoryFormats);
1933 nvAssert(b->layer[i].usable ==
1934 !!b->layer[i].supportedSurfaceMemoryFormats);
1935
1936 ret->layer[i].usable = a->layer[i].usable && b->layer[i].usable;
1937
1938 ret->layer[i].supportedSurfaceMemoryFormats =
1939 a->layer[i].supportedSurfaceMemoryFormats &
1940 b->layer[i].supportedSurfaceMemoryFormats;
1941
1942 IntersectScalingUsageBounds(&a->layer[i].scaling,
1943 &b->layer[i].scaling,
1944 &ret->layer[i].scaling);
1945 }
1946 }
UsageBoundsEqual(const struct NvKmsUsageBounds * a,const struct NvKmsUsageBounds * b)1947 NvBool UsageBoundsEqual(
1948 const struct NvKmsUsageBounds *a,
1949 const struct NvKmsUsageBounds *b)
1950 {
1951 NvU32 layer;
1952
1953 for (layer = 0; layer < ARRAY_LEN(a->layer); layer++) {
1954 if (!nvEvoLayerUsageBoundsEqual(a, b, layer)) {
1955 return FALSE;
1956 }
1957 }
1958
1959 return TRUE;
1960 }
1961
nvAllocatePreFlipBandwidth(NVDevEvoPtr pDevEvo,struct NvKmsFlipWorkArea * pWorkArea)1962 NvBool nvAllocatePreFlipBandwidth(NVDevEvoPtr pDevEvo,
1963 struct NvKmsFlipWorkArea *pWorkArea)
1964 {
1965 NVValidateImpOneDispHeadParamsRec *timingsParams = NULL;
1966 struct NvKmsUsageBounds *currentAndNew = NULL;
1967 struct NvKmsUsageBounds *guaranteedAndCurrent = NULL;
1968 NVDispEvoPtr pDispEvo;
1969 NvU32 head;
1970 NvBool recheckIMP = FALSE;
1971 NvBool ret = TRUE;
1972
1973 if (!pDevEvo->isSOCDisplay) {
1974 return TRUE;
1975 }
1976
1977 timingsParams =
1978 nvCalloc(NVKMS_MAX_HEADS_PER_DISP, sizeof(*timingsParams));
1979 if (timingsParams == NULL) {
1980 return FALSE;
1981 }
1982
1983 currentAndNew =
1984 nvCalloc(NVKMS_MAX_HEADS_PER_DISP, sizeof(*currentAndNew));
1985 if (currentAndNew == NULL) {
1986 nvFree(timingsParams);
1987 return FALSE;
1988 }
1989
1990 guaranteedAndCurrent =
1991 nvCalloc(NVKMS_MAX_HEADS_PER_DISP, sizeof(*guaranteedAndCurrent));
1992 if (guaranteedAndCurrent == NULL) {
1993 nvFree(timingsParams);
1994 nvFree(currentAndNew);
1995 return FALSE;
1996 }
1997
1998 pDispEvo = pDevEvo->pDispEvo[0];
1999
2000 // SOC Display never has more than one disp
2001 nvAssert(pDevEvo->nDispEvo == 1);
2002
2003 for (head = 0; head < pDevEvo->numHeads; head++) {
2004 NVDispHeadStateEvoRec *pHeadState =
2005 &pDispEvo->headState[head];
2006 const struct NvKmsUsageBounds *pCurrent =
2007 &pDevEvo->gpus[0].headState[head].preallocatedUsage;
2008 const struct NvKmsUsageBounds *pNew =
2009 &pWorkArea->sd[0].head[head].newState.usage;
2010
2011 if (pHeadState->activeRmId == 0) {
2012 continue;
2013 }
2014
2015 timingsParams[head].pConnectorEvo = pHeadState->pConnectorEvo;
2016 timingsParams[head].activeRmId = pHeadState->activeRmId;
2017 timingsParams[head].pixelDepth = pHeadState->pixelDepth;
2018 timingsParams[head].pTimings = &pHeadState->timings;
2019 timingsParams[head].enableDsc = (pHeadState->dscInfo.type !=
2020 NV_DSC_INFO_EVO_TYPE_DISABLED);
2021 timingsParams[head].b2Heads1Or =
2022 (pHeadState->mergeMode != NV_EVO_MERGE_MODE_DISABLED);
2023
2024 nvUnionUsageBounds(pCurrent, pNew, ¤tAndNew[head]);
2025 nvUnionUsageBounds(&pHeadState->timings.viewPort.guaranteedUsage,
2026 pCurrent, &guaranteedAndCurrent[head]);
2027
2028 if (!ValidateUsageBounds(pDevEvo,
2029 head,
2030 pNew,
2031 &guaranteedAndCurrent[head])) {
2032 recheckIMP = TRUE;
2033 }
2034
2035 nvUnionUsageBounds(&guaranteedAndCurrent[head], pNew,
2036 &guaranteedAndCurrent[head]);
2037 timingsParams[head].pUsage = &guaranteedAndCurrent[head];
2038 }
2039
2040 if (recheckIMP) {
2041 ret = nvValidateImpOneDisp(pDispEvo, timingsParams,
2042 FALSE /* requireBootClocks */,
2043 NV_EVO_REALLOCATE_BANDWIDTH_MODE_PRE,
2044 NULL /* pMinIsoBandwidthKBPS */,
2045 NULL /* pMinDramFloorKBPS */);
2046 if (ret) {
2047 for (head = 0; head < pDevEvo->numHeads; head++) {
2048 pDevEvo->gpus[0].headState[head].preallocatedUsage =
2049 currentAndNew[head];
2050 }
2051 }
2052 }
2053
2054 nvFree(timingsParams);
2055 nvFree(currentAndNew);
2056 nvFree(guaranteedAndCurrent);
2057
2058 if (ret) {
2059 nvScheduleLowerDispBandwidthTimer(pDevEvo);
2060 }
2061
2062 return ret;
2063 }
2064
2065 /*!
2066 * If the satellite channel is active then pre-NVDisplay hardware does not allow
2067 * to change its usage bounds in non-interlock update. The nvSetUsageBoundsEvo()
2068 * code path for pre-NVDisplay hardware, interlocks the satellite channels with
2069 * the usage bounds update. This makes it essential to poll for
2070 * NO_METHOD_PENDING state of the satellite channels, otherwise blocking
2071 * pre-flip IMP update will also get stuck.
2072 *
2073 * It is not possible to interlock flip-locked satellite channels with the core
2074 * channel usage bounds update; in that case, reject the flip. Do not allow
2075 * client to make any change in surface usage bounds parameters without
2076 * deactivating channel first, if channel is flip-locked.
2077 */
PrepareToDoPreFlipIMP(NVDevEvoPtr pDevEvo,struct NvKmsFlipWorkArea * pWorkArea)2078 static NvBool PrepareToDoPreFlipIMP(NVDevEvoPtr pDevEvo,
2079 struct NvKmsFlipWorkArea *pWorkArea)
2080 {
2081 NvU64 startTime = 0;
2082 NvU32 timeout = 2000000; /* 2 seconds */
2083 NvU32 sd;
2084
2085 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2086 NVEvoSubDevPtr pEvoSubDev = &pDevEvo->gpus[sd];
2087 NvU32 head;
2088
2089 for (head = 0; head < pDevEvo->numHeads; head++) {
2090 NVEvoHeadControlPtr pHC =
2091 &pEvoSubDev->headControl[head];
2092 const NVEvoSubDevHeadStateRec *pCurrentFlipState =
2093 &pDevEvo->gpus[sd].headState[head];
2094 const NVSurfaceEvoRec *pCurrentBaseSurf =
2095 pCurrentFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT];
2096 const struct NvKmsUsageBounds *pCurrentUsage =
2097 &pCurrentFlipState->usage;
2098
2099 NVFlipEvoHwState *pNewFlipState =
2100 &pWorkArea->sd[sd].head[head].newState;
2101 const NVSurfaceEvoRec *pNewBaseSurf =
2102 pNewFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT];
2103 struct NvKmsUsageBounds *pNewUsage =
2104 &pNewFlipState->usage;
2105
2106 struct NvKmsUsageBounds *pPreFlipUsage =
2107 &pWorkArea->sd[sd].head[head].preFlipUsage;
2108
2109 NvU32 layer;
2110
2111 nvUnionUsageBounds(pNewUsage, pCurrentUsage, pPreFlipUsage);
2112
2113 if (pDevEvo->hal->caps.supportsNonInterlockedUsageBoundsUpdate) {
2114 /*
2115 * NVDisplay does not interlock the satellite channel
2116 * with its usage bounds update.
2117 */
2118 continue;
2119 }
2120
2121 /*
2122 * If head is flip-locked then do not change usage
2123 * bounds while base channel is active.
2124 */
2125 if (pHC->flipLock &&
2126 /* If the base channel is active before and after flip then
2127 * current and new base usage bounds should be same. */
2128 ((pNewBaseSurf != NULL &&
2129 pCurrentBaseSurf != NULL &&
2130 !nvEvoLayerUsageBoundsEqual(pCurrentUsage,
2131 pNewUsage, NVKMS_MAIN_LAYER)) ||
2132 /* If the base channel is active before flip then current and
2133 * preflip base usage bounds should be same. */
2134 (pCurrentBaseSurf != NULL &&
2135 !nvEvoLayerUsageBoundsEqual(pCurrentUsage,
2136 pPreFlipUsage, NVKMS_MAIN_LAYER)))) {
2137 return FALSE;
2138 }
2139
2140 /*
2141 * Poll for NO_METHOD_PENDING state if usage
2142 * bounds of the channel are changed.
2143 */
2144 for (layer = 0; layer < pDevEvo->head[head].numLayers; layer++) {
2145 if (!nvEvoLayerUsageBoundsEqual(pCurrentUsage,
2146 pPreFlipUsage, layer) &&
2147 !nvEvoPollForNoMethodPending(pDevEvo,
2148 sd,
2149 pDevEvo->head[head].layer[layer],
2150 &startTime,
2151 timeout)) {
2152 return FALSE;
2153 }
2154 }
2155 }
2156 }
2157
2158 return TRUE;
2159 }
2160
2161 /*!
2162 * Tasks need to perform before triggering flip, they all should be done here.
2163 *
2164 * If necessary, raise usage bounds and/or disable MidFrameAndDWCFWatermark
2165 * (bug 200508242) in the core channel and do an IMP update.
2166 *
2167 * Note that this function only raises usage bounds and/or disables
2168 * MidFrameAndDWCFWatermark, never lowers usage bounds and/or enables
2169 * MidFrameAndDWCFWatermark. This allows it to run before queuing a flip even
2170 * if there are still pending flips in a base channel.
2171 */
PreFlipIMP(NVDevEvoPtr pDevEvo,const struct NvKmsFlipWorkArea * pWorkArea)2172 static void PreFlipIMP(NVDevEvoPtr pDevEvo,
2173 const struct NvKmsFlipWorkArea *pWorkArea)
2174 {
2175 NvU32 head, sd;
2176 NVDispEvoPtr pDispEvo;
2177
2178 FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2179 NVEvoUpdateState updateState = { };
2180 NvBool update = FALSE;
2181
2182 for (head = 0; head < pDispEvo->pDevEvo->numHeads; head++) {
2183 const NVFlipEvoHwState *pNewState =
2184 &pWorkArea->sd[sd].head[head].newState;
2185 const struct NvKmsUsageBounds *pPreFlipUsage =
2186 &pWorkArea->sd[sd].head[head].preFlipUsage;
2187 struct NvKmsUsageBounds *pCurrentUsage =
2188 &pDevEvo->gpus[sd].headState[head].usage;
2189
2190 if (!UsageBoundsEqual(pCurrentUsage, pPreFlipUsage)) {
2191 update |= nvSetUsageBoundsEvo(pDevEvo, sd, head,
2192 pPreFlipUsage, &updateState);
2193 }
2194
2195 if (!pDevEvo->gpus[sd].
2196 headState[head].disableMidFrameAndDWCFWatermark &&
2197 pNewState->disableMidFrameAndDWCFWatermark) {
2198
2199 nvEnableMidFrameAndDWCFWatermark(pDevEvo,
2200 sd,
2201 head,
2202 FALSE /* enable */,
2203 &updateState);
2204 update = TRUE;
2205 }
2206 }
2207
2208 if (update) {
2209 nvDoIMPUpdateEvo(pDispEvo, &updateState);
2210 }
2211 }
2212 }
2213
LowerDispBandwidth(void * dataPtr,NvU32 dataU32)2214 static void LowerDispBandwidth(void *dataPtr, NvU32 dataU32)
2215 {
2216 NVValidateImpOneDispHeadParamsRec timingsParams[NVKMS_MAX_HEADS_PER_DISP];
2217 struct NvKmsUsageBounds *guaranteedAndCurrent;
2218 NVDevEvoPtr pDevEvo = dataPtr;
2219 NVDispEvoPtr pDispEvo;
2220 NvU32 head;
2221 NvBool ret;
2222
2223 guaranteedAndCurrent =
2224 nvCalloc(1, sizeof(*guaranteedAndCurrent) * NVKMS_MAX_HEADS_PER_DISP);
2225 if (guaranteedAndCurrent == NULL) {
2226 nvAssert(guaranteedAndCurrent != NULL);
2227 return;
2228 }
2229
2230 nvkms_memset(&timingsParams, 0, sizeof(timingsParams));
2231
2232 pDispEvo = pDevEvo->pDispEvo[0];
2233
2234 // SOC Display never has more than one disp
2235 nvAssert(pDevEvo->nDispEvo == 1);
2236
2237 for (head = 0; head < pDevEvo->numHeads; head++) {
2238 NVDispHeadStateEvoRec *pHeadState =
2239 &pDispEvo->headState[head];
2240 const struct NvKmsUsageBounds *pGuaranteed =
2241 &pHeadState->timings.viewPort.guaranteedUsage;
2242 const struct NvKmsUsageBounds *pCurrent =
2243 &pDevEvo->gpus[0].headState[head].usage;
2244
2245 if (pHeadState->activeRmId == 0) {
2246 continue;
2247 }
2248
2249 timingsParams[head].pConnectorEvo = pHeadState->pConnectorEvo;
2250 timingsParams[head].activeRmId = pHeadState->activeRmId;
2251 timingsParams[head].pixelDepth = pHeadState->pixelDepth;
2252 timingsParams[head].pTimings = &pHeadState->timings;
2253 timingsParams[head].enableDsc = (pHeadState->dscInfo.type !=
2254 NV_DSC_INFO_EVO_TYPE_DISABLED);
2255 timingsParams[head].b2Heads1Or =
2256 (pHeadState->mergeMode != NV_EVO_MERGE_MODE_DISABLED);
2257
2258 nvUnionUsageBounds(pGuaranteed, pCurrent, &guaranteedAndCurrent[head]);
2259 timingsParams[head].pUsage = &guaranteedAndCurrent[head];
2260 }
2261
2262 ret = nvValidateImpOneDisp(pDispEvo, timingsParams,
2263 FALSE /* requireBootClocks */,
2264 NV_EVO_REALLOCATE_BANDWIDTH_MODE_POST,
2265 NULL /* pMinIsoBandwidthKBPS */,
2266 NULL /* pMinDramFloorKBPS */);
2267 if (ret) {
2268 for (head = 0; head < pDevEvo->numHeads; head++) {
2269 pDevEvo->gpus[0].headState[head].preallocatedUsage =
2270 pDevEvo->gpus[0].headState[head].usage;
2271 }
2272 }
2273
2274 nvAssert(ret);
2275
2276 nvFree(guaranteedAndCurrent);
2277 }
2278
nvCancelLowerDispBandwidthTimer(NVDevEvoPtr pDevEvo)2279 void nvCancelLowerDispBandwidthTimer(NVDevEvoPtr pDevEvo)
2280 {
2281 nvkms_free_timer(pDevEvo->lowerDispBandwidthTimer);
2282 pDevEvo->lowerDispBandwidthTimer = NULL;
2283 }
2284
nvScheduleLowerDispBandwidthTimer(NVDevEvoPtr pDevEvo)2285 void nvScheduleLowerDispBandwidthTimer(NVDevEvoPtr pDevEvo)
2286 {
2287 nvAssert(pDevEvo->isSOCDisplay);
2288
2289 nvCancelLowerDispBandwidthTimer(pDevEvo);
2290
2291 pDevEvo->lowerDispBandwidthTimer =
2292 nvkms_alloc_timer(LowerDispBandwidth,
2293 pDevEvo,
2294 0, /* dataU32 */
2295 30000000 /* 30 seconds */);
2296 }
2297
2298 /*!
2299 * Check whether the core, base, and overlay channels are idle (i.e. no methods
2300 * pending in the corresponding pushbuffer) and lower the usage bounds if
2301 * possible.
2302 */
TryLoweringUsageBoundsOneHead(NVDevEvoPtr pDevEvo,NvU32 sd,NvU32 head,NVEvoUpdateState * updateState)2303 static NvBool TryLoweringUsageBoundsOneHead(NVDevEvoPtr pDevEvo, NvU32 sd,
2304 NvU32 head,
2305 NVEvoUpdateState *updateState)
2306 {
2307 const NVEvoSubDevHeadStateRec *pHeadState =
2308 &pDevEvo->gpus[sd].headState[head];
2309 const struct NvKmsUsageBounds *pCurrent = &pHeadState->usage;
2310 const struct NvKmsUsageBounds *pTarget = &pHeadState->targetUsage;
2311 struct NvKmsUsageBounds newUsage = *pCurrent;
2312 NvBool changed = FALSE;
2313 NvBool scheduleLater = FALSE;
2314 int i;
2315
2316 for (i = 0; i < pDevEvo->head[head].numLayers; i++) {
2317 if (pCurrent->layer[i].usable && !pTarget->layer[i].usable) {
2318 NvBool isMethodPending;
2319
2320 if (pDevEvo->hal->IsChannelMethodPending(
2321 pDevEvo,
2322 pDevEvo->head[head].layer[i],
2323 sd,
2324 &isMethodPending) && !isMethodPending) {
2325 newUsage.layer[i] = pTarget->layer[i];
2326 changed = TRUE;
2327 } else {
2328 scheduleLater = TRUE;
2329 }
2330 } else if ((pCurrent->layer[i].usable && pTarget->layer[i].usable) &&
2331 ((pCurrent->layer[i].supportedSurfaceMemoryFormats !=
2332 pTarget->layer[i].supportedSurfaceMemoryFormats) ||
2333 (!nvEvoScalingUsageBoundsEqual(&pCurrent->layer[i].scaling,
2334 &pTarget->layer[i].scaling)))) {
2335 NvBool isMethodPending;
2336
2337 if (pDevEvo->hal->IsChannelMethodPending(
2338 pDevEvo,
2339 pDevEvo->head[head].layer[i],
2340 sd,
2341 &isMethodPending) && !isMethodPending) {
2342 newUsage.layer[i] = pTarget->layer[i];
2343 changed = TRUE;
2344 } else {
2345 scheduleLater = TRUE;
2346 }
2347 }
2348 }
2349
2350 if (scheduleLater) {
2351 SchedulePostFlipIMPTimer(pDevEvo);
2352 }
2353
2354 if (changed) {
2355 changed = nvSetUsageBoundsEvo(pDevEvo, sd, head, &newUsage,
2356 updateState);
2357 }
2358
2359 return changed;
2360 }
2361
2362 static NvBool
TryEnablingMidFrameAndDWCFWatermarkOneHead(NVDevEvoPtr pDevEvo,NvU32 sd,NvU32 head,NVEvoUpdateState * updateState)2363 TryEnablingMidFrameAndDWCFWatermarkOneHead(NVDevEvoPtr pDevEvo,
2364 NvU32 sd,
2365 NvU32 head,
2366 NVEvoUpdateState *updateState)
2367 {
2368 const NVEvoSubDevHeadStateRec *pHeadState =
2369 &pDevEvo->gpus[sd].headState[head];
2370 NvBool changed = FALSE;
2371
2372 if (pHeadState->disableMidFrameAndDWCFWatermark &&
2373 !pHeadState->targetDisableMidFrameAndDWCFWatermark) {
2374
2375 NvBool isIdle;
2376
2377 if (pDevEvo->hal->IsChannelIdle(pDevEvo,
2378 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER],
2379 sd,
2380 &isIdle) && isIdle) {
2381 nvEnableMidFrameAndDWCFWatermark(pDevEvo,
2382 sd,
2383 head,
2384 TRUE /* enable */,
2385 updateState);
2386 changed = TRUE;
2387 } else {
2388 // Schedule another timer to try again later.
2389 SchedulePostFlipIMPTimer(pDevEvo);
2390 }
2391 }
2392
2393 return changed;
2394 }
2395
2396 static void
TryToDoPostFlipIMP(void * dataPtr,NvU32 dataU32)2397 TryToDoPostFlipIMP(void *dataPtr, NvU32 dataU32)
2398 {
2399 NVDevEvoPtr pDevEvo = dataPtr;
2400 NvU32 head, sd;
2401 NVDispEvoPtr pDispEvo;
2402
2403 pDevEvo->postFlipIMPTimer = NULL;
2404
2405 FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2406 NVEvoUpdateState updateState = { };
2407 NvBool update = FALSE;
2408
2409 for (head = 0; head < pDispEvo->pDevEvo->numHeads; head++) {
2410 if (TryLoweringUsageBoundsOneHead(pDevEvo, sd, head,
2411 &updateState)) {
2412 update = TRUE;
2413 }
2414
2415 if (TryEnablingMidFrameAndDWCFWatermarkOneHead(
2416 pDevEvo,
2417 sd,
2418 head,
2419 &updateState)) {
2420 update = TRUE;
2421 }
2422 }
2423
2424 if (update) {
2425 nvDoIMPUpdateEvo(pDispEvo, &updateState);
2426 }
2427 }
2428 }
2429
SchedulePostFlipIMPTimer(NVDevEvoPtr pDevEvo)2430 static void SchedulePostFlipIMPTimer(NVDevEvoPtr pDevEvo)
2431 {
2432 if (!pDevEvo->postFlipIMPTimer) {
2433 pDevEvo->postFlipIMPTimer =
2434 nvkms_alloc_timer(
2435 TryToDoPostFlipIMP,
2436 pDevEvo,
2437 0, /* dataU32 */
2438 10000000 /* 10 seconds */);
2439 }
2440 }
2441
nvEvoCancelPostFlipIMPTimer(NVDevEvoPtr pDevEvo)2442 void nvEvoCancelPostFlipIMPTimer(NVDevEvoPtr pDevEvo)
2443 {
2444 nvkms_free_timer(pDevEvo->postFlipIMPTimer);
2445 pDevEvo->postFlipIMPTimer = NULL;
2446 }
2447
2448 /*!
2449 * If necessary, schedule a timer to see if usage bounds can be lowered.
2450 */
SchedulePostFlipIMP(NVDevEvoPtr pDevEvo)2451 static void SchedulePostFlipIMP(NVDevEvoPtr pDevEvo)
2452 {
2453 NvU32 head, sd;
2454 NVDispEvoPtr pDispEvo;
2455
2456 // If a timer is already scheduled, do nothing.
2457 if (pDevEvo->postFlipIMPTimer) {
2458 return;
2459 }
2460
2461 FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2462 for (head = 0; head < pDispEvo->pDevEvo->numHeads; head++) {
2463 const NVEvoSubDevHeadStateRec *pHeadState =
2464 &pDevEvo->gpus[sd].headState[head];
2465
2466 if (!UsageBoundsEqual(&pHeadState->usage,
2467 &pHeadState->targetUsage) ||
2468 (pHeadState->disableMidFrameAndDWCFWatermark !=
2469 pHeadState->targetDisableMidFrameAndDWCFWatermark)) {
2470
2471 SchedulePostFlipIMPTimer(pDevEvo);
2472 return;
2473 }
2474 }
2475 }
2476 }
2477
SkipLayerPendingFlips(NVDevEvoRec * pDevEvo,const NvBool trashPendingMethods,const NvBool unblockMethodsInExecutation,struct NvKmsFlipWorkArea * pWorkArea)2478 static void SkipLayerPendingFlips(NVDevEvoRec *pDevEvo,
2479 const NvBool trashPendingMethods,
2480 const NvBool unblockMethodsInExecutation,
2481 struct NvKmsFlipWorkArea *pWorkArea)
2482 {
2483 NvU64 startTime = 0;
2484 const NvU32 timeout = 2000000; /* 2 seconds */
2485 struct {
2486 struct {
2487 struct {
2488 NvU32 oldAccelMask;
2489 } head[NVKMS_MAX_HEADS_PER_DISP];
2490 } sd[NVKMS_MAX_SUBDEVICES];
2491 } accelState = { };
2492 NvU32 sd, head;
2493
2494 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2495 if (!pWorkArea->sd[sd].changed) {
2496 continue;
2497 }
2498
2499 for (head = 0; head < NVKMS_MAX_HEADS_PER_DISP; head++) {
2500 const NVFlipEvoHwState *pFlipState =
2501 &pWorkArea->sd[sd].head[head].newState;
2502
2503 if (!pFlipState->skipLayerPendingFlips[NVKMS_MAIN_LAYER]||
2504 !pFlipState->dirty.layer[NVKMS_MAIN_LAYER]) {
2505 continue;
2506 }
2507
2508 pDevEvo->hal->AccelerateChannel(
2509 pDevEvo,
2510 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER],
2511 sd,
2512 trashPendingMethods,
2513 unblockMethodsInExecutation,
2514 &accelState.sd[sd].head[head].oldAccelMask);
2515 }
2516 }
2517
2518 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2519 if (!pWorkArea->sd[sd].changed) {
2520 continue;
2521 }
2522
2523 for (head = 0; head < NVKMS_MAX_HEADS_PER_DISP; head++) {
2524 const NVFlipEvoHwState *pFlipState =
2525 &pWorkArea->sd[sd].head[head].newState;
2526
2527 if (!pFlipState->skipLayerPendingFlips[NVKMS_MAIN_LAYER] ||
2528 !pFlipState->dirty.layer[NVKMS_MAIN_LAYER]) {
2529 continue;
2530 }
2531
2532 if (unblockMethodsInExecutation) {
2533 if (!nvEvoPollForNoMethodPending(pDevEvo,
2534 sd,
2535 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER],
2536 &startTime,
2537 timeout)) {
2538 nvAssert(!"Failed to idle the main layer channel");
2539 }
2540 } else {
2541 if (!nvEvoPollForEmptyChannel(pDevEvo->head[head].layer[NVKMS_MAIN_LAYER],
2542 sd,
2543 &startTime,
2544 timeout)) {
2545 nvAssert(!"Failed to empty the main layer channel");
2546 }
2547 }
2548
2549 pDevEvo->hal->ResetChannelAccelerators(
2550 pDevEvo,
2551 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER],
2552 sd,
2553 trashPendingMethods,
2554 unblockMethodsInExecutation,
2555 accelState.sd[sd].head[head].oldAccelMask);
2556 }
2557 }
2558 }
2559
nvPreFlip(NVDevEvoRec * pDevEvo,struct NvKmsFlipWorkArea * pWorkArea,const NvBool applyAllowVrr,const NvBool allowVrr,const NvBool skipUpdate)2560 void nvPreFlip(NVDevEvoRec *pDevEvo,
2561 struct NvKmsFlipWorkArea *pWorkArea,
2562 const NvBool applyAllowVrr,
2563 const NvBool allowVrr,
2564 const NvBool skipUpdate)
2565 {
2566 NvU32 sd, head;
2567 NVDispEvoRec *pDispEvo;
2568
2569 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2570
2571 if (!pWorkArea->sd[sd].changed) {
2572 continue;
2573 }
2574
2575 for (head = 0; head < NVKMS_MAX_HEADS_PER_DISP; head++) {
2576 // Increase refCnt of surfaces used AFTER flip
2577 nvUpdateSurfacesFlipRefCount(
2578 pDevEvo,
2579 head,
2580 &pWorkArea->sd[sd].head[head].newState,
2581 NV_TRUE);
2582
2583 nvRefTmoLutSurfacesEvo(
2584 pDevEvo,
2585 &pWorkArea->sd[sd].head[head].newState,
2586 head);
2587 }
2588 }
2589
2590 PreFlipIMP(pDevEvo, pWorkArea);
2591
2592 if (!skipUpdate) {
2593 /* Trash flips pending in channel which are not yet in execution */
2594 SkipLayerPendingFlips(pDevEvo, TRUE /* trashPendingMethods */,
2595 FALSE /* unblockMethodsInExecutation */,
2596 pWorkArea);
2597 }
2598
2599 if (applyAllowVrr) {
2600 nvSetVrrActive(pDevEvo, allowVrr);
2601 }
2602
2603 /*
2604 * Update flip metering for Frame pacing smoothing/frame splitting for direct
2605 * drive and adaptive sync VRR, and override the flip timestamp if
2606 * necessary.
2607 */
2608 FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2609 for (NvU32 inputHead = 0; inputHead < pDevEvo->numHeads; inputHead++) {
2610 const NVDispHeadStateEvoRec *pInputHeadState =
2611 &pDispEvo->headState[inputHead];
2612 const struct NvKmsVrrFramePacingInfo *pInputVrrFramePacingInfo =
2613 &pInputHeadState->vrrFramePacingInfo;
2614 const NvU32 headsMask = pInputHeadState->mergeModeVrrSecondaryHeadMask |
2615 NVBIT(inputHead);
2616
2617 /*
2618 * XXX[2Heads1OR] Implement per api-head frame pacing and remove this
2619 * mergeMode check and NVDispEvoRec::mergeModeVrrSecondaryHeadMask.
2620 */
2621 if (pInputHeadState->mergeMode == NV_EVO_MERGE_MODE_SECONDARY) {
2622 continue;
2623 }
2624
2625 #if defined(DEBUG)
2626 FOR_EACH_EVO_HW_HEAD_IN_MASK(headsMask, head) {
2627 const NVFlipEvoHwState *pInputHeadNewState =
2628 &pWorkArea->sd[sd].head[inputHead].newState;
2629 const NVFlipEvoHwState *pNewState =
2630 &pWorkArea->sd[sd].head[head].newState;
2631
2632 nvAssert(pNewState->dirty.layer[NVKMS_MAIN_LAYER] ==
2633 pInputHeadNewState->dirty.layer[NVKMS_MAIN_LAYER]);
2634 }
2635 #endif
2636
2637 FOR_EACH_EVO_HW_HEAD_IN_MASK(headsMask, head) {
2638 NVFlipEvoHwState *pNewState =
2639 &pWorkArea->sd[sd].head[head].newState;
2640 if (pNewState->dirty.layer[NVKMS_MAIN_LAYER]) {
2641 nvTrackAndDelayFlipForVrrSwFramePacing(pDispEvo,
2642 pInputVrrFramePacingInfo,
2643 &pNewState->layer[NVKMS_MAIN_LAYER]);
2644 }
2645 }
2646 }
2647 }
2648 }
2649
nvPostFlip(NVDevEvoRec * pDevEvo,struct NvKmsFlipWorkArea * pWorkArea,const NvBool skipUpdate,const NvBool applyAllowVrr,NvS32 * pVrrSemaphoreIndex)2650 void nvPostFlip(NVDevEvoRec *pDevEvo,
2651 struct NvKmsFlipWorkArea *pWorkArea,
2652 const NvBool skipUpdate,
2653 const NvBool applyAllowVrr,
2654 NvS32 *pVrrSemaphoreIndex)
2655 {
2656 NvU32 sd, head;
2657
2658 if (!skipUpdate) {
2659 /* Unblock flips which are stuck in execution */
2660 SkipLayerPendingFlips(pDevEvo, FALSE /* trashPendingMethods */,
2661 TRUE /* unblockMethodsInExecutation */,
2662 pWorkArea);
2663 }
2664
2665 if (applyAllowVrr) {
2666 *pVrrSemaphoreIndex = nvIncVrrSemaphoreIndex(pDevEvo);
2667 } else {
2668 // TODO Schedule vrr unstall; per-disp/per-device?
2669 }
2670
2671 for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2672 if (!pWorkArea->sd[sd].changed) {
2673 continue;
2674 }
2675
2676 for (head = 0; head < NVKMS_MAX_HEADS_PER_DISP; head++) {
2677 // Decrease refCnt of surfaces used BEFORE the flip
2678 nvUpdateSurfacesFlipRefCount(
2679 pDevEvo,
2680 head,
2681 &pWorkArea->sd[sd].head[head].oldState,
2682 NV_FALSE);
2683
2684 nvUnrefTmoLutSurfacesEvo(
2685 pDevEvo,
2686 &pWorkArea->sd[sd].head[head].oldState,
2687 head);
2688 }
2689 }
2690
2691 if (!skipUpdate) {
2692 // Note that usage bounds are not lowered here, because the flip
2693 // queued by this function may not occur until later. Instead, schedule
2694 // a timer for later to check if the usage bounds can be lowered.
2695 SchedulePostFlipIMP(pDevEvo);
2696
2697 pDevEvo->skipConsoleRestore = FALSE;
2698 }
2699 }
2700
AllocPreSyncpt(NVDevEvoRec * pDevEvo,NVEvoChannel * pChannel,const NvU32 id)2701 static NvBool AllocPreSyncpt(NVDevEvoRec *pDevEvo,
2702 NVEvoChannel *pChannel, const NvU32 id)
2703 {
2704 NVSurfaceDescriptor surfaceDesc;
2705
2706 /*! use id value to check the global table */
2707 if (!pDevEvo->preSyncptTable[id].allocated) {
2708 /*! Register - allocate and bind surface descriptor for syncpt*/
2709 if (!nvRmEvoAllocAndBindSyncpt(pDevEvo,
2710 pChannel,
2711 id,
2712 &surfaceDesc,
2713 &pDevEvo->preSyncptTable[id])) {
2714 nvAssert(!"Failed to register pre-syncpt");
2715 return FALSE;
2716 }
2717
2718 /*! Fill the Entry in Global Table */
2719 pDevEvo->preSyncptTable[id].channelMask |= pChannel->channelMask;
2720 } else {
2721 /*!
2722 * syncpt found, just bind the surface descriptor of this syncpt
2723 * to the window if it is not already.
2724 */
2725 if ((pDevEvo->preSyncptTable[id].channelMask &
2726 pChannel->channelMask) == 0) {
2727
2728 NvU32 ret =
2729 pDevEvo->hal->BindSurfaceDescriptor(pDevEvo,
2730 pChannel, &pDevEvo->preSyncptTable[id].surfaceDesc);
2731 if (ret != NVOS_STATUS_SUCCESS) {
2732 nvAssert(!"Failed to bind surface descriptor for pre-syncpt");
2733 }
2734
2735 pDevEvo->preSyncptTable[id].channelMask |= pChannel->channelMask;
2736 /*! hSyncpt already allocated for id*/
2737 }
2738 }
2739
2740 return TRUE;
2741 }
2742
RegisterPreSyncpt(NVDevEvoRec * pDevEvo,struct NvKmsFlipWorkArea * pWorkArea)2743 static NvBool RegisterPreSyncpt(NVDevEvoRec *pDevEvo,
2744 struct NvKmsFlipWorkArea *pWorkArea)
2745 {
2746 NvU32 sd;
2747 NvU32 ret = TRUE;
2748 const NVDispEvoRec *pDispEvo;
2749
2750 pDevEvo->pAllSyncptUsedInCurrentFlip =
2751 nvCalloc(1, sizeof(NvBool) * NV_SYNCPT_GLOBAL_TABLE_LENGTH);
2752 if (pDevEvo->pAllSyncptUsedInCurrentFlip == NULL) {
2753 ret = FALSE;
2754 goto done;
2755 }
2756
2757 FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2758 NvU32 head;
2759 for (head = 0; head < ARRAY_LEN(pWorkArea->sd[sd].head); head++) {
2760 NVFlipEvoHwState *pFlipState =
2761 &pWorkArea->sd[sd].head[head].newState;
2762 NvU32 layer;
2763
2764 for (layer = 0; layer < ARRAY_LEN(pFlipState->layer); layer++) {
2765 NVFlipSyncObjectEvoHwState *pFlipSyncObject =
2766 &pFlipState->layer[layer].syncObject;
2767 NvU32 preSyncpt = pFlipSyncObject->u.syncpts.preSyncpt;
2768
2769 if (!pFlipState->dirty.layerSyncObjects[layer] ||
2770 !pFlipSyncObject->usingSyncpt ||
2771 !pFlipSyncObject->u.syncpts.isPreSyncptSpecified) {
2772 continue;
2773 }
2774
2775 if (!AllocPreSyncpt(pDevEvo, pDevEvo->head[head].layer[layer],
2776 preSyncpt)) {
2777 ret = FALSE;
2778 goto done;
2779 }
2780
2781 pDevEvo->pAllSyncptUsedInCurrentFlip[preSyncpt] = NV_TRUE;
2782 }
2783 }
2784 }
2785
2786 done:
2787 nvFree(pDevEvo->pAllSyncptUsedInCurrentFlip);
2788 pDevEvo->pAllSyncptUsedInCurrentFlip = NULL;
2789
2790 return ret;
2791 }
2792
nvPrepareToDoPreFlip(NVDevEvoRec * pDevEvo,struct NvKmsFlipWorkArea * pWorkArea)2793 NvBool nvPrepareToDoPreFlip(NVDevEvoRec *pDevEvo,
2794 struct NvKmsFlipWorkArea *pWorkArea)
2795 {
2796 if (!RegisterPreSyncpt(pDevEvo, pWorkArea)) {
2797 return FALSE;
2798 }
2799
2800 if (!PrepareToDoPreFlipIMP(pDevEvo, pWorkArea)) {
2801 return FALSE;
2802 }
2803
2804 return TRUE;
2805 }
2806
nvAssignNVFlipEvoHwState(NVDevEvoRec * pDevEvo,const struct NvKmsPerOpenDev * pOpenDev,const NvU32 sd,const NvU32 head,const struct NvKmsFlipCommonParams * pParams,const NvBool allowVrr,NVFlipEvoHwState * pFlipHwState)2807 NvBool nvAssignNVFlipEvoHwState(NVDevEvoRec *pDevEvo,
2808 const struct NvKmsPerOpenDev *pOpenDev,
2809 const NvU32 sd,
2810 const NvU32 head,
2811 const struct NvKmsFlipCommonParams *pParams,
2812 const NvBool allowVrr,
2813 NVFlipEvoHwState *pFlipHwState)
2814 {
2815 const NVDispEvoRec *pDispEvo = pDevEvo->gpus[sd].pDispEvo;
2816 const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
2817 const struct NvKmsUsageBounds *pPossibleUsage =
2818 &pHeadState->timings.viewPort.possibleUsage;
2819
2820 if (!nvUpdateFlipEvoHwState(pOpenDev, pDevEvo, sd, head, pParams,
2821 &pHeadState->timings, pHeadState->tilePosition,
2822 pFlipHwState, allowVrr)) {
2823 return FALSE;
2824 }
2825
2826 nvOverrideScalingUsageBounds(pDevEvo, head, pFlipHwState, pPossibleUsage);
2827
2828 if (!nvValidateFlipEvoHwState(pDevEvo, head, &pHeadState->timings,
2829 pFlipHwState)) {
2830 return FALSE;
2831 }
2832
2833 if (!nvSetTmoLutSurfacesEvo(pDevEvo, pFlipHwState, head)) {
2834 return FALSE;
2835 }
2836
2837 return TRUE;
2838 }
2839
2840 /*!
2841 * Wait for idle on a set of the main layer channels.
2842 *
2843 * \param[in,out] pDevEvo The device.
2844 * \param[in] idleChannelMaskPerSd The channel masks per subdevice that
2845 * we should wait to be idle.
2846 * \param[in] allowForceIdle Whether we should force idle a channel
2847 * or just assert if the idle times out.
2848 */
nvIdleMainLayerChannels(NVDevEvoPtr pDevEvo,const NVEvoChannelMask * idleChannelMaskPerSd,NvBool allowStopBase)2849 void nvIdleMainLayerChannels(
2850 NVDevEvoPtr pDevEvo,
2851 const NVEvoChannelMask *idleChannelMaskPerSd,
2852 NvBool allowStopBase)
2853 {
2854 NvU64 startTime = 0;
2855 NvBool allChannelsIdle = FALSE;
2856 NVDispEvoPtr pDispEvo;
2857 NvU32 dispIndex, head;
2858 NVEvoChannelMask busyChannelMaskPerSd[NVKMS_MAX_SUBDEVICES] = { };
2859
2860 /*
2861 * Wait up to 2 seconds for all channels to be idle, and gather a list of
2862 * all busy channels.
2863 */
2864 while (!allChannelsIdle) {
2865
2866 const NvU32 timeout = 2000000; /* 2 seconds */
2867 NvBool anyChannelBusy = FALSE;
2868
2869 FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
2870 for (head = 0; head < pDevEvo->numHeads; head++) {
2871 NVEvoChannelPtr pMainLayerChannel =
2872 pDevEvo->head[head].layer[NVKMS_MAIN_LAYER];
2873 if (idleChannelMaskPerSd[pDispEvo->displayOwner] &
2874 pMainLayerChannel->channelMask) {
2875
2876 NvBool isMethodPending = FALSE;
2877 if (!pDevEvo->hal->IsChannelMethodPending(
2878 pDevEvo,
2879 pMainLayerChannel,
2880 pDispEvo->displayOwner,
2881 &isMethodPending)
2882 || isMethodPending) {
2883
2884 /* Mark this channel as busy. */
2885 busyChannelMaskPerSd[pDispEvo->displayOwner] |=
2886 pMainLayerChannel->channelMask;
2887 anyChannelBusy = TRUE;
2888 } else {
2889 /*
2890 * Mark this channel as no longer busy, in case its
2891 * flip completed while we were waiting on another
2892 * channel.
2893 */
2894 busyChannelMaskPerSd[pDispEvo->displayOwner] &=
2895 ~pMainLayerChannel->channelMask;
2896 }
2897 }
2898 }
2899 }
2900
2901 if (!anyChannelBusy) {
2902 allChannelsIdle = TRUE;
2903 break;
2904 }
2905
2906 /* Break out of the loop if we exceed the timeout. */
2907 if (nvExceedsTimeoutUSec(pDevEvo, &startTime, timeout)) {
2908 break;
2909 }
2910
2911 nvkms_yield();
2912 }
2913
2914 if (!allChannelsIdle) {
2915 /*
2916 * At least one channel was still idle after the 2 second timeout
2917 * above.
2918 */
2919 if (!allowStopBase) {
2920 /*
2921 * The caller of this function expected this wait for idle not to
2922 * time out.
2923 */
2924 nvEvoLogDev(pDevEvo, EVO_LOG_WARN,
2925 "Timeout while waiting for idle.");
2926 } else {
2927 /*
2928 * Idle all base channels that were still busy when the wait above
2929 * timed out.
2930 */
2931 NVEvoIdleChannelState idleChannelState = { };
2932
2933 FOR_ALL_EVO_DISPLAYS(pDispEvo, dispIndex, pDevEvo) {
2934 idleChannelState.subdev[pDispEvo->displayOwner].channelMask =
2935 busyChannelMaskPerSd[pDispEvo->displayOwner];
2936 }
2937
2938 pDevEvo->hal->ForceIdleSatelliteChannelIgnoreLock(
2939 pDevEvo, &idleChannelState);
2940 }
2941 }
2942 }
2943
nvNeedToToggleFlipLock(const NVDispEvoRec * pDispEvo,const NvU32 head,const NvBool enable)2944 NvBool nvNeedToToggleFlipLock(const NVDispEvoRec *pDispEvo,
2945 const NvU32 head, const NvBool enable)
2946 {
2947 const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
2948 const NVEvoSubDevPtr pEvoSubDev = &pDevEvo->gpus[pDispEvo->displayOwner];
2949 const NVEvoHeadControlPtr pHC = &pEvoSubDev->headControl[head];
2950 NvBool needToToggle = FALSE;
2951
2952 if (!enable && pHC->flipLock) {
2953 /*
2954 * This channel is currently using fliplock in the config that
2955 * is being torn down; idle its base channel and disable
2956 * fliplock.
2957 */
2958 needToToggle = TRUE;
2959 }
2960
2961 if (enable && ((pHC->serverLock != NV_EVO_NO_LOCK) ||
2962 (pHC->clientLock != NV_EVO_NO_LOCK))) {
2963 /*
2964 * This channel will be using fliplock for swap groups in the
2965 * new config; idle its base channel and enable fliplock.
2966 */
2967 nvAssert(!HEAD_MASK_QUERY(pEvoSubDev->flipLockProhibitedHeadMask,
2968 head));
2969 needToToggle = TRUE;
2970 }
2971
2972 return needToToggle;
2973 }
2974
nvToggleFlipLockPerDisp(NVDispEvoRec * pDispEvo,const NvU32 headMask,const NvBool enable)2975 void nvToggleFlipLockPerDisp(NVDispEvoRec *pDispEvo, const NvU32 headMask,
2976 const NvBool enable)
2977 {
2978 NvU32 head;
2979 NVEvoUpdateState updateState = { };
2980 const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
2981
2982 for (head = 0; head < pDevEvo->numHeads; head++) {
2983 if ((headMask & NVBIT(head)) != 0x0) {
2984 NvU32 setEnable = enable;
2985
2986 if (!nvUpdateFlipLockEvoOneHead(pDispEvo, head, &setEnable,
2987 TRUE /* set */,
2988 &updateState)) {
2989 nvEvoLogDev(pDevEvo, EVO_LOG_WARN,
2990 "Failed to toggle fliplock for swapgroups.");
2991 }
2992 }
2993 }
2994
2995 if (!nvIsUpdateStateEmpty(pDevEvo, &updateState)) {
2996 nvEvoUpdateAndKickOff(pDispEvo, TRUE, &updateState,
2997 TRUE /* releaseElv */);
2998 }
2999 }
3000