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                               &params);
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, &params);
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, &currentAndNew[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