1 /*
2  * SPDX-FileCopyrightText: Copyright (c) 2010 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 /*
25  * This file contains implementations of the EVO HAL methods for display class
26  * 2.x.
27  */
28 
29 #include "nvkms-dma.h"
30 #include "nvkms-types.h"
31 #include "nvkms-rmapi.h"
32 #include "nvkms-surface.h"
33 
34 #include "nvkms-evo.h"
35 #include "nvkms-evo1.h"
36 #include "nvkms-ctxdma.h"
37 
38 #include <nvmisc.h>
39 
40 #include <class/cl5070.h> // NV5070_NOTIFICATION_STATUS
41 
42 #include <class/cl917c.h> // NV917C_BASE_CHANNEL_DMA
43 #include <class/cl917b.h> // GK104DispOverlayImmControlPio
44 #include <class/cl917e.h> // NV917E_OVERLAY_CHANNEL_DMA
45 #include <class/cl917cswspare.h> // NV917C_SET_SPARE_{PRE,POST}_UPDATE_TRAP
46 
47 #include <class/cl917d.h>         // NV917D_CORE_CHANNEL_DMA
48 #include <class/cl917dcrcnotif.h> // NV917D_NOTIFIER_CRC
49 #include <class/cl927d.h>         // NV927D_CORE_CHANNEL_DMA
50 #include <class/cl977d.h>         // NV977D_CORE_CHANNEL_DMA
51 #include <class/cl947d.h>         // NV947D_CORE_CHANNEL_DMA
52 #include <class/cl907dswspare.h>
53 
54 #include <ctrl/ctrl5070/ctrl5070chnc.h> // NV5070_CTRL_CMD_STOP_BASE_PARAMS
55 
56 ct_assert(NV_EVO_LOCK_PIN_0 >
57           NV917D_HEAD_SET_CONTROL_MASTER_LOCK_PIN_INTERNAL_SCAN_LOCK__SIZE_1);
58 ct_assert(NV_EVO_LOCK_PIN_0 >
59           NV917D_HEAD_SET_CONTROL_MASTER_LOCK_PIN_INTERNAL_FLIP_LOCK__SIZE_1);
60 
61 /** Number of CRCs supported by hardware on NV917D hardware (Comp and SF/SOR) */
62 #define NV_EVO2_NUM_CRC_FIELDS 2
63 
64 /** Flags read from CRCNotifier on NV917D hardware (Comp, SF/SOR Ovf and count) */
65 #define NV_EVO2_NUM_CRC_FLAGS 3
66 
67 #define NV_EVO2_SUPPORTED_DITHERING_MODES                               \
68     ((1 << NV_KMS_DPY_ATTRIBUTE_REQUESTED_DITHERING_MODE_AUTO)        | \
69      (1 << NV_KMS_DPY_ATTRIBUTE_REQUESTED_DITHERING_MODE_DYNAMIC_2X2) | \
70      (1 << NV_KMS_DPY_ATTRIBUTE_REQUESTED_DITHERING_MODE_STATIC_2X2)  | \
71      (1 << NV_KMS_DPY_ATTRIBUTE_REQUESTED_DITHERING_MODE_TEMPORAL))
72 
73 #define NV_EVO2_SUPPORTED_CURSOR_COMP_BLEND_MODES      \
74     ((1 << NVKMS_COMPOSITION_BLENDING_MODE_NON_PREMULT_ALPHA) | \
75      (1 << NVKMS_COMPOSITION_BLENDING_MODE_PREMULT_ALPHA))
76 
77 static void
78 EvoSetCursorImage(NVDevEvoPtr pDevEvo,
79                   const int head,
80                   const NVSurfaceEvoRec *pSurfaceEvo,
81                   NVEvoUpdateState *updateState,
82                   const struct NvKmsCompositionParams *pCursorCompParams);
83 
84 static void
85 EvoPushSetLUTContextDmaMethodsForOneSd(NVDevEvoRec *pDevEvo,
86                                        const NvU32 sd,
87                                        const NvU32 head,
88                                        const NvU32 ctxdma,
89                                        NvBool enableBaseLut,
90                                        const NvBool enableOutputLut,
91                                        NVEvoUpdateState *updateState);
92 static void
93 EvoPushUpdateComposition(NVDevEvoPtr pDevEvo,
94                          const int head,
95                          const NVFlipChannelEvoHwState *pBaseHwState,
96                          const NVFlipChannelEvoHwState *pOverlayHwState,
97                          NVEvoUpdateState *updateState,
98                          NvBool bypassComposition);
99 
InitChannelCaps90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel)100 static void InitChannelCaps90(NVDevEvoPtr pDevEvo,
101                               NVEvoChannelPtr pChannel)
102 {
103     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0) {
104         static const NVEvoChannelCaps OverlayCaps = {
105             /*
106              * Overlay supports timestamp flips on class 9x7e, but error checks
107              * that it doesn't exceed 61 bits.
108              */
109             .validTimeStampBits = 61,
110             /* Overlay does not support tearing/immediate flips. */
111             .tearingFlips = FALSE,
112             .vrrTearingFlips = FALSE,
113             /* Overlay does not support per-eye stereo flips. */
114             .perEyeStereoFlips = FALSE,
115         };
116 
117         pChannel->caps = OverlayCaps;
118     }
119     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL) != 0) {
120         static const NVEvoChannelCaps BaseCaps = {
121             /*
122              * Base supports timestamp flips on class 9x7c, but error checks
123              * that it doesn't exceed 61 bits.
124              */
125             .validTimeStampBits = 61,
126             /* Base supports tearing/immediate flips. */
127             .tearingFlips = TRUE,
128             /* Base supports VRR tearing flips. */
129             .vrrTearingFlips = TRUE,
130             /* Base supports per-eye stereo flips. */
131             .perEyeStereoFlips = TRUE,
132         };
133 
134         pChannel->caps = BaseCaps;
135     }
136 }
137 
EvoInitChannel90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel)138 static void EvoInitChannel90(NVDevEvoPtr pDevEvo, NVEvoChannelPtr pChannel)
139 {
140     const NvBool isCore =
141             FLD_TEST_DRF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE,
142                            pChannel->channelMask);
143 
144     InitChannelCaps90(pDevEvo, pChannel);
145 
146     /* Set up core channel state. */
147     if (isCore) {
148         NvU32 head;
149 
150         for (head = 0; head < pDevEvo->numHeads; head++) {
151             nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_DEFAULT_BASE_COLOR(head), 1);
152             nvDmaSetEvoMethodData(pChannel,
153                 DRF_NUM(917D, _HEAD_SET_DEFAULT_BASE_COLOR, _RED,   0) |
154                 DRF_NUM(917D, _HEAD_SET_DEFAULT_BASE_COLOR, _GREEN, 0) |
155                 DRF_NUM(917D, _HEAD_SET_DEFAULT_BASE_COLOR, _BLUE,  0));
156         }
157     }
158 
159     /* Set up base channel state. */
160     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL) != 0) {
161         NvU32 head = NV_EVO_CHANNEL_MASK_BASE_HEAD_NUMBER(pChannel->channelMask);
162         NvU32 sd;
163 
164         for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
165             pDevEvo->pSubDevices[sd]->baseComp[head].initialized = FALSE;
166         }
167 
168         // For now we only support USE_CORE_LUT mode, but sending this method every
169         // flip causes an error check to fire for tearing flips even if the LUT mode
170         // isn't changing.  So instead, program it here.  ApplyBaseFlipOverrides()
171         // will force the first flip to be non-tearing.
172         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_BASE_LUT_LO, 1);
173         nvDmaSetEvoMethodData(pChannel, DRF_DEF(917C, _SET_BASE_LUT_LO, _ENABLE,
174                               _USE_CORE_LUT));
175         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_OUTPUT_LUT_LO, 1);
176         nvDmaSetEvoMethodData(pChannel, DRF_DEF(917C, _SET_OUTPUT_LUT_LO, _ENABLE,
177                               _USE_CORE_LUT));
178     }
179 
180     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0) {
181         NvU32 head = NV_EVO_CHANNEL_MASK_OVERLAY_HEAD_NUMBER(pChannel->channelMask);
182         NvU32 sd;
183 
184         for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
185             pDevEvo->pSubDevices[sd]->overlayComp[head].initialized = FALSE;
186         }
187     }
188 }
189 
EvoInitWindowMapping90(const NVDispEvoRec * pDispEvo,NVEvoModesetUpdateState * pModesetUpdateState)190 static void EvoInitWindowMapping90(const NVDispEvoRec *pDispEvo,
191                                    NVEvoModesetUpdateState *pModesetUpdateState)
192 {
193     /* Fixed window mapping on EVO 2 -- nothing to do. */
194 }
195 
196 /*
197  * These values are the same between all overlay
198  * (7E_SURFACE_SET_PARAMS_FORMAT_) EVO classes.
199  *
200  * Return 0 in the case of an unrecognized NvKmsSurfaceMemoryFormat.
201  */
EvoOverlayFormatFromKmsFormat91(enum NvKmsSurfaceMemoryFormat format)202 static NvU32 EvoOverlayFormatFromKmsFormat91(enum NvKmsSurfaceMemoryFormat format)
203 {
204     switch (format) {
205         case NvKmsSurfaceMemoryFormatI8:
206             return 0;
207         case NvKmsSurfaceMemoryFormatR5G6B5:
208             return 0;
209         case NvKmsSurfaceMemoryFormatA1R5G5B5:
210         case NvKmsSurfaceMemoryFormatX1R5G5B5:
211             return NV917E_SURFACE_SET_PARAMS_FORMAT_A1R5G5B5;
212         case NvKmsSurfaceMemoryFormatA8R8G8B8:
213         case NvKmsSurfaceMemoryFormatX8R8G8B8:
214             return NV917E_SURFACE_SET_PARAMS_FORMAT_A8R8G8B8;
215         case NvKmsSurfaceMemoryFormatA2B10G10R10:
216         case NvKmsSurfaceMemoryFormatX2B10G10R10:
217             return NV917E_SURFACE_SET_PARAMS_FORMAT_A2B10G10R10;
218         case NvKmsSurfaceMemoryFormatRF16GF16BF16AF16:
219         case NvKmsSurfaceMemoryFormatRF16GF16BF16XF16:
220             return NV917E_SURFACE_SET_PARAMS_FORMAT_RF16_GF16_BF16_AF16;
221         case NvKmsSurfaceMemoryFormatR16G16B16A16:
222             return NV917E_SURFACE_SET_PARAMS_FORMAT_R16_G16_B16_A16;
223         case NvKmsSurfaceMemoryFormatA8B8G8R8:
224         case NvKmsSurfaceMemoryFormatX8B8G8R8:
225         case NvKmsSurfaceMemoryFormatRF32GF32BF32AF32:
226         case NvKmsSurfaceMemoryFormatY8_U8__Y8_V8_N422:
227         case NvKmsSurfaceMemoryFormatU8_Y8__V8_Y8_N422:
228         case NvKmsSurfaceMemoryFormatY8___U8V8_N444:
229         case NvKmsSurfaceMemoryFormatY8___V8U8_N444:
230         case NvKmsSurfaceMemoryFormatY8___U8V8_N422:
231         case NvKmsSurfaceMemoryFormatY8___V8U8_N422:
232         case NvKmsSurfaceMemoryFormatY8___U8V8_N420:
233         case NvKmsSurfaceMemoryFormatY8___V8U8_N420:
234         case NvKmsSurfaceMemoryFormatY10___U10V10_N444:
235         case NvKmsSurfaceMemoryFormatY10___V10U10_N444:
236         case NvKmsSurfaceMemoryFormatY10___U10V10_N422:
237         case NvKmsSurfaceMemoryFormatY10___V10U10_N422:
238         case NvKmsSurfaceMemoryFormatY10___U10V10_N420:
239         case NvKmsSurfaceMemoryFormatY10___V10U10_N420:
240         case NvKmsSurfaceMemoryFormatY12___U12V12_N444:
241         case NvKmsSurfaceMemoryFormatY12___V12U12_N444:
242         case NvKmsSurfaceMemoryFormatY12___U12V12_N422:
243         case NvKmsSurfaceMemoryFormatY12___V12U12_N422:
244         case NvKmsSurfaceMemoryFormatY12___U12V12_N420:
245         case NvKmsSurfaceMemoryFormatY12___V12U12_N420:
246         case NvKmsSurfaceMemoryFormatY8___U8___V8_N444:
247         case NvKmsSurfaceMemoryFormatY8___U8___V8_N420:
248             return 0;
249     }
250 
251     return 0;
252 }
253 
EvoSetRasterParams90(NVDevEvoPtr pDevEvo,int head,const NVHwModeTimingsEvo * pTimings,const NVEvoColorRec * pOverscanColor,NVEvoUpdateState * updateState)254 static void EvoSetRasterParams90(NVDevEvoPtr pDevEvo, int head,
255                                  const NVHwModeTimingsEvo *pTimings,
256                                  const NVEvoColorRec *pOverscanColor,
257                                  NVEvoUpdateState *updateState)
258 {
259     NVEvoChannelPtr pChannel = pDevEvo->core;
260     NvU32 overscanColor =
261         DRF_NUM(917D, _HEAD_SET_OVERSCAN_COLOR, _RED, pOverscanColor->red) |
262         DRF_NUM(917D, _HEAD_SET_OVERSCAN_COLOR, _GRN, pOverscanColor->green) |
263         DRF_NUM(917D, _HEAD_SET_OVERSCAN_COLOR, _BLU, pOverscanColor->blue);
264 
265     /* These methods should only apply to a single pDpy */
266     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
267 
268     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
269 
270     // XXX[AGP]: These methods are sequential and could use an incrementing
271     // method, but it's not clear if there's a bug in EVO that causes corruption
272     // sometimes.  Play it safe and send methods with count=1.
273 
274     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_OVERSCAN_COLOR(head), 1);
275     nvDmaSetEvoMethodData(pChannel, overscanColor);
276 
277     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_RASTER_SIZE(head), 1);
278     nvDmaSetEvoMethodData(pChannel,
279         DRF_NUM(917D, _HEAD_SET_RASTER_SIZE, _WIDTH, pTimings->rasterSize.x) |
280         DRF_NUM(917D, _HEAD_SET_RASTER_SIZE, _HEIGHT, pTimings->rasterSize.y));
281 
282     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_RASTER_SYNC_END(head), 1);
283     nvDmaSetEvoMethodData(pChannel,
284         DRF_NUM(917D, _HEAD_SET_RASTER_SYNC_END, _X, pTimings->rasterSyncEnd.x) |
285         DRF_NUM(917D, _HEAD_SET_RASTER_SYNC_END, _Y, pTimings->rasterSyncEnd.y));
286 
287     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_RASTER_BLANK_END(head), 1);
288     nvDmaSetEvoMethodData(pChannel,
289         DRF_NUM(917D, _HEAD_SET_RASTER_BLANK_END, _X, pTimings->rasterBlankEnd.x) |
290         DRF_NUM(917D, _HEAD_SET_RASTER_BLANK_END, _Y, pTimings->rasterBlankEnd.y));
291 
292     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_RASTER_BLANK_START(head), 1);
293     nvDmaSetEvoMethodData(pChannel,
294         DRF_NUM(917D, _HEAD_SET_RASTER_BLANK_START, _X, pTimings->rasterBlankStart.x) |
295         DRF_NUM(917D, _HEAD_SET_RASTER_BLANK_START, _Y, pTimings->rasterBlankStart.y));
296 
297     if (pTimings->interlaced) {
298         nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_RASTER_VERT_BLANK2(head), 1);
299         nvDmaSetEvoMethodData(pChannel,
300                 DRF_NUM(917D, _HEAD_SET_RASTER_VERT_BLANK2, _YSTART,
301                         pTimings->rasterVertBlank2Start) |
302                 DRF_NUM(917D, _HEAD_SET_RASTER_VERT_BLANK2, _YEND,
303                         pTimings->rasterVertBlank2End));
304     }
305 
306     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PIXEL_CLOCK_FREQUENCY(head), 1);
307     nvDmaSetEvoMethodData(pChannel,
308         DRF_NUM(917D, _HEAD_SET_PIXEL_CLOCK_FREQUENCY, _HERTZ,
309                 pTimings->pixelClock * 1000) |
310         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_FREQUENCY, _ADJ1000DIV1001,_FALSE));
311 
312     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PIXEL_CLOCK_CONFIGURATION(head), 1);
313     nvDmaSetEvoMethodData(pChannel,
314         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_CONFIGURATION, _MODE, _CLK_CUSTOM) |
315         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_CONFIGURATION, _NOT_DRIVER, _FALSE) |
316         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_CONFIGURATION, _ENABLE_HOPPING, _FALSE) |
317         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_CONFIGURATION, _HOPPING_MODE, _VBLANK));
318 
319     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX(head), 1);
320     nvDmaSetEvoMethodData(pChannel,
321         DRF_NUM(917D, _HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, _HERTZ,
322                 pTimings->pixelClock * 1000) |
323         DRF_DEF(917D, _HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, _ADJ1000DIV1001,_FALSE));
324 }
325 
326 /*
327  * Wrapper for EvoSetRasterParams90 which additionally sends the HDMI 3D
328  * control methods.
329  */
EvoSetRasterParams91(NVDevEvoPtr pDevEvo,int head,const NVHwModeTimingsEvo * pTimings,const NvU8 tilePosition,const NVDscInfoEvoRec * pDscInfo,const NVEvoColorRec * pOverscanColor,NVEvoUpdateState * updateState)330 static void EvoSetRasterParams91(NVDevEvoPtr pDevEvo, int head,
331                                  const NVHwModeTimingsEvo *pTimings,
332                                  const NvU8 tilePosition,
333                                  const NVDscInfoEvoRec *pDscInfo,
334                                  const NVEvoColorRec *pOverscanColor,
335                                  NVEvoUpdateState *updateState)
336 {
337     NVEvoChannelPtr pChannel = pDevEvo->core;
338     NvU32 hdmiStereoCtrl =
339         DRF_DEF(917D, _HEAD_SET_HDMI_CTRL, _STEREO3D_STRUCTURE, _FRAME_PACKED) |
340         DRF_NUM(917D, _HEAD_SET_HDMI_CTRL, _HDMI_VIC, 0);
341 
342     nvAssert(tilePosition == 0);
343     nvAssert(pDscInfo->type == NV_DSC_INFO_EVO_TYPE_DISABLED);
344 
345     EvoSetRasterParams90(pDevEvo, head,
346                          pTimings,
347                          pOverscanColor, updateState);
348 
349     if (pTimings->hdmi3D) {
350         hdmiStereoCtrl |=
351             DRF_DEF(917D, _HEAD_SET_HDMI_CTRL, _VIDEO_FORMAT, _STEREO3D);
352     } else {
353         hdmiStereoCtrl |=
354             DRF_DEF(917D, _HEAD_SET_HDMI_CTRL, _VIDEO_FORMAT, _NORMAL);
355     }
356 
357     nvDmaSetStartEvoMethod(pChannel,
358         NV917D_HEAD_SET_VACTIVE_SPACE_COLOR(head), 1);
359     nvDmaSetEvoMethodData(pChannel,
360         DRF_NUM(917D, _HEAD_SET_VACTIVE_SPACE_COLOR, _RED_CR, 0) |
361 #if defined(DEBUG)
362         DRF_NUM(917D, _HEAD_SET_VACTIVE_SPACE_COLOR, _GRN_Y,  512) |
363 #else
364         DRF_NUM(917D, _HEAD_SET_VACTIVE_SPACE_COLOR, _GRN_Y,  0) |
365 #endif
366         DRF_NUM(917D, _HEAD_SET_VACTIVE_SPACE_COLOR, _BLU_CB, 0));
367 
368     nvDmaSetStartEvoMethod(pChannel,
369         NV917D_HEAD_SET_HDMI_CTRL(head), 1);
370     nvDmaSetEvoMethodData(pChannel, hdmiStereoCtrl);
371 }
372 
EvoSetProcAmp90(NVDispEvoPtr pDispEvo,const NvU32 head,NVEvoUpdateState * updateState)373 static void EvoSetProcAmp90(NVDispEvoPtr pDispEvo, const NvU32 head,
374                             NVEvoUpdateState *updateState)
375 {
376     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
377     NVEvoChannelPtr pChannel = pDevEvo->core;
378     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
379     NvU32 dynRange;
380 
381     /* These methods should only apply to a single pDpyEvo */
382     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
383 
384     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
385 
386     // These NVT defines match the HEAD_SET_PROCAMP ones.
387     ct_assert(NVT_COLORIMETRY_RGB == NV917D_HEAD_SET_PROCAMP_COLOR_SPACE_RGB);
388     ct_assert(NVT_COLORIMETRY_YUV_601 == NV917D_HEAD_SET_PROCAMP_COLOR_SPACE_YUV_601);
389     ct_assert(NVT_COLORIMETRY_YUV_709 == NV917D_HEAD_SET_PROCAMP_COLOR_SPACE_YUV_709);
390     ct_assert(NVT_COLOR_RANGE_FULL == NV917D_HEAD_SET_PROCAMP_RANGE_COMPRESSION_DISABLE);
391     ct_assert(NVT_COLOR_RANGE_LIMITED == NV917D_HEAD_SET_PROCAMP_RANGE_COMPRESSION_ENABLE);
392 
393     if (pHeadState->procAmp.colorRange == NVT_COLOR_RANGE_FULL) {
394         dynRange = DRF_DEF(917D, _HEAD_SET_PROCAMP, _DYNAMIC_RANGE, _VESA);
395     } else {
396         nvAssert(pHeadState->procAmp.colorRange == NVT_COLOR_RANGE_LIMITED);
397         dynRange = DRF_DEF(917D, _HEAD_SET_PROCAMP, _DYNAMIC_RANGE, _CEA);
398     }
399 
400     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PROCAMP(head), 1);
401     nvDmaSetEvoMethodData(pChannel,
402         DRF_NUM(917D, _HEAD_SET_PROCAMP, _COLOR_SPACE,
403                 pHeadState->procAmp.colorimetry) |
404         DRF_DEF(917D, _HEAD_SET_PROCAMP, _CHROMA_LPF, _AUTO) |
405         DRF_NUM(917D, _HEAD_SET_PROCAMP, _SAT_COS,
406                 pHeadState->procAmp.satCos) |
407         DRF_NUM(917D, _HEAD_SET_PROCAMP, _SAT_SINE, 0) |
408         dynRange |
409         DRF_NUM(917D, _HEAD_SET_PROCAMP, _RANGE_COMPRESSION,
410                 pHeadState->procAmp.colorRange));
411 }
412 
EvoSetHeadControl90(NVDevEvoPtr pDevEvo,int sd,int head,NVEvoUpdateState * updateState)413 static void EvoSetHeadControl90(NVDevEvoPtr pDevEvo, int sd, int head,
414                                 NVEvoUpdateState *updateState)
415 {
416     NVEvoChannelPtr pChannel = pDevEvo->core;
417     NVEvoSubDevPtr pEvoSubDev = &pDevEvo->gpus[sd];
418     /*
419      * NOTE: This function should only push state to the hardware based on data
420      * in the pHC.  If not, then we may miss updates due to the memcmp of the
421      * HeadControl structure in UpdateEvoLockState().
422      */
423     NVEvoHeadControlPtr pHC = &pEvoSubDev->headControl[head];
424     NvU32 data = 0, pin;
425     NvU32 serverLockMode, clientLockMode;
426 
427     /* These methods should only apply to a single subdevice */
428     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
429 
430     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
431 
432     switch (pHC->serverLock) {
433     case NV_EVO_NO_LOCK:
434         serverLockMode = NV917D_HEAD_SET_CONTROL_MASTER_LOCK_MODE_NO_LOCK;
435         break;
436     case NV_EVO_FRAME_LOCK:
437         serverLockMode = NV917D_HEAD_SET_CONTROL_MASTER_LOCK_MODE_FRAME_LOCK;
438         break;
439     case NV_EVO_RASTER_LOCK:
440         serverLockMode = NV917D_HEAD_SET_CONTROL_MASTER_LOCK_MODE_RASTER_LOCK;
441         break;
442     default:
443         nvAssert(!"Invalid server lock mode");
444         return;
445     }
446 
447     switch (pHC->clientLock) {
448     case NV_EVO_NO_LOCK:
449         clientLockMode = NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_MODE_NO_LOCK;
450         break;
451     case NV_EVO_FRAME_LOCK:
452         clientLockMode = NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_MODE_FRAME_LOCK;
453         break;
454     case NV_EVO_RASTER_LOCK:
455         clientLockMode = NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_MODE_RASTER_LOCK;
456         break;
457     default:
458         nvAssert(!"Invalid client lock mode");
459         return;
460     }
461 
462     // Convert head control state to EVO method values.
463     if (pHC->interlaced) {
464         data |= DRF_DEF(917D, _HEAD_SET_CONTROL, _STRUCTURE, _INTERLACED);
465     } else {
466         data |= DRF_DEF(917D, _HEAD_SET_CONTROL, _STRUCTURE, _PROGRESSIVE);
467     }
468 
469     nvAssert(pHC->serverLockPin != NV_EVO_LOCK_PIN_ERROR);
470     nvAssert(pHC->clientLockPin != NV_EVO_LOCK_PIN_ERROR);
471     nvAssert(pHC->flipLockPin != NV_EVO_LOCK_PIN_ERROR);
472 
473     if (NV_EVO_LOCK_PIN_IS_INTERNAL(pHC->serverLockPin)) {
474         pin = pHC->serverLockPin - NV_EVO_LOCK_PIN_INTERNAL_0;
475         /*
476          * dispClass_02.mfs says:
477          * "master lock pin, if internal, must be set to the corresponding
478          * internal pin for that head" (error check #12)
479          * (Note that this is only enforced when scanlock master is enabled)
480          */
481         nvAssert(pHC->serverLock == NV_EVO_NO_LOCK || pin == head);
482         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _MASTER_LOCK_PIN,
483                         NV917D_HEAD_SET_CONTROL_MASTER_LOCK_PIN_INTERNAL_SCAN_LOCK(pin));
484     } else {
485         pin = pHC->serverLockPin - NV_EVO_LOCK_PIN_0;
486         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _MASTER_LOCK_PIN,
487                         NV917D_HEAD_SET_CONTROL_MASTER_LOCK_PIN_LOCK_PIN(pin));
488     }
489     data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _MASTER_LOCK_MODE, serverLockMode);
490 
491     if (clientLockMode == NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_MODE_NO_LOCK) {
492         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _SLAVE_LOCK_PIN,
493                         NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_PIN_UNSPECIFIED);
494     } else if (NV_EVO_LOCK_PIN_IS_INTERNAL(pHC->clientLockPin)) {
495         pin = pHC->clientLockPin - NV_EVO_LOCK_PIN_INTERNAL_0;
496         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _SLAVE_LOCK_PIN,
497                         NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_PIN_INTERNAL_SCAN_LOCK(pin));
498     } else {
499         pin = pHC->clientLockPin - NV_EVO_LOCK_PIN_0;
500         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _SLAVE_LOCK_PIN,
501                         NV917D_HEAD_SET_CONTROL_SLAVE_LOCK_PIN_LOCK_PIN(pin));
502     }
503     data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _SLAVE_LOCK_MODE, clientLockMode);
504     data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _SLAVE_LOCKOUT_WINDOW,
505                     pHC->clientLockoutWindow);
506 
507     /*
508      * Interlaced with stereo lock mode is not supported.
509      *
510      * We always enable stereo lock when it's available and either framelock
511      * or rasterlock is in use.
512      */
513     if (pHC->stereoLocked) {
514         nvAssert(!pHC->interlaced);
515 
516         if (pHC->serverLock != NV_EVO_NO_LOCK) {
517             data |= DRF_NUM(927D, _HEAD_SET_CONTROL, _MASTER_STEREO_LOCK_MODE,
518                             NV927D_HEAD_SET_CONTROL_MASTER_STEREO_LOCK_MODE_ENABLE);
519         }
520         if (pHC->clientLock != NV_EVO_NO_LOCK) {
521             data |= DRF_NUM(927D, _HEAD_SET_CONTROL, _SLAVE_STEREO_LOCK_MODE,
522                             NV927D_HEAD_SET_CONTROL_SLAVE_STEREO_LOCK_MODE_ENABLE);
523         }
524     }
525 
526     /*
527      * Changing the flip lock pin induces a head shutdown.  We want to avoid
528      * this in two cases:
529      *
530      * 1) When transitioning from the UEFI console, the flip lock pin is
531      *    currently set to UNSPECIFIED, so we want to preserve that setting
532      *    if possible to avoid an unnecessary flicker.
533      *
534      * 2) While framelock is enabled, we need to avoid head shutdown when
535      *    transitioning to and from fliplock to guarantee no loss of stereo
536      *    sync.
537      *
538      * To guarantee stereo sync while also avoiding unnecessary flicker when
539      * transitioning from UEFI, we'll set the flip lock pin to UNSPECIFIED
540      * unless fliplock, frame lock, or raster lock are enabled.  Enabling
541      * framelock may induce one head shutdown when transitioning away from
542      * UNSPECIFIED, but then enabling/disabling fliplock after that will
543      * have no effect on the fliplock pin.
544      */
545     if (!pHC->flipLock &&
546         (pHC->serverLock == NV_EVO_NO_LOCK) &&
547         (pHC->clientLock == NV_EVO_NO_LOCK)) {
548 
549         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _FLIP_LOCK_PIN,
550                         NV917D_HEAD_SET_CONTROL_FLIP_LOCK_PIN_UNSPECIFIED);
551     } else if (NV_EVO_LOCK_PIN_IS_INTERNAL(pHC->flipLockPin)) {
552         pin = pHC->flipLockPin - NV_EVO_LOCK_PIN_INTERNAL_0;
553         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _FLIP_LOCK_PIN,
554                         NV917D_HEAD_SET_CONTROL_FLIP_LOCK_PIN_INTERNAL_FLIP_LOCK(pin));
555     } else {
556         pin = pHC->flipLockPin - NV_EVO_LOCK_PIN_0;
557         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _FLIP_LOCK_PIN,
558                         NV917D_HEAD_SET_CONTROL_FLIP_LOCK_PIN_LOCK_PIN(pin));
559     }
560     if (pHC->flipLock) {
561         data |= DRF_DEF(917D, _HEAD_SET_CONTROL, _FLIP_LOCK, _ENABLE);
562     }
563 
564     nvAssert(pHC->stereoPin != NV_EVO_LOCK_PIN_ERROR);
565     if (NV_EVO_LOCK_PIN_IS_INTERNAL(pHC->stereoPin)) {
566         /*
567          * dispClass_02.mfs says:
568          * "stereo pin, if internal, must be set to the corresponding internal
569          * pin for that head" (error check #14)
570          * So just ignore which pin we selected; no sense in wasting cycles
571          * keeping track of it
572          */
573         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _STEREO_PIN,
574                         NV917D_HEAD_SET_CONTROL_STEREO_PIN_INTERNAL_SCAN_LOCK(head));
575     } else {
576         pin = pHC->stereoPin - NV_EVO_LOCK_PIN_0;
577         data |= DRF_NUM(917D, _HEAD_SET_CONTROL, _STEREO_PIN,
578                         NV917D_HEAD_SET_CONTROL_STEREO_PIN_LOCK_PIN(pin));
579     }
580 
581     // Send the method.
582     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTROL(head), 1);
583     nvDmaSetEvoMethodData(pChannel, data);
584 
585     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_LOCK_CHAIN(head), 1);
586     nvDmaSetEvoMethodData(pChannel, DRF_NUM(917D, _HEAD_SET_LOCK_CHAIN, _POSITION,
587                                   pHC->lockChainPosition));
588 }
589 
EvoSetHeadRefClk90(NVDevEvoPtr pDevEvo,int head,NvBool external,NVEvoUpdateState * updateState)590 static void EvoSetHeadRefClk90(NVDevEvoPtr pDevEvo, int head, NvBool external,
591                                NVEvoUpdateState *updateState)
592 {
593     NVEvoChannelPtr pChannel = pDevEvo->core;
594 
595     /* These methods should only apply to a single subdevice */
596     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
597 
598     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
599 
600     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_SW_SPARE_A(head), 1);
601     nvDmaSetEvoMethodData(pChannel, external ?
602                 DRF_DEF(907D, _HEAD_SET_SW_SPARE_A_CODE, _VPLL_REF, _GSYNC) :
603                 DRF_DEF(907D, _HEAD_SET_SW_SPARE_A_CODE, _VPLL_REF, _NO_PREF));
604 }
605 
EvoDACSetControl90(const NVConnectorEvoRec * pConnectorEvo,const enum nvKmsTimingsProtocol protocol,const NvU32 orIndex,const NvU32 headMask)606 static void EvoDACSetControl90(const NVConnectorEvoRec *pConnectorEvo,
607                                const enum nvKmsTimingsProtocol protocol,
608                                const NvU32 orIndex,
609                                const NvU32 headMask)
610 {
611     NVDevEvoPtr pDevEvo = pConnectorEvo->pDispEvo->pDevEvo;
612     NVEvoChannelPtr pChannel = pDevEvo->core;
613 
614     /* These methods should only apply to a single pDpy */
615     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
616 
617     if (headMask != 0) {
618         nvAssert(protocol == NVKMS_PROTOCOL_DAC_RGB);
619     }
620 
621     nvDmaSetStartEvoMethod(pChannel, NV917D_DAC_SET_CONTROL(orIndex), 1);
622     nvDmaSetEvoMethodData(pChannel,
623         DRF_NUM(917D, _DAC_SET_CONTROL, _OWNER_MASK, headMask) |
624         DRF_DEF(917D, _DAC_SET_CONTROL, _PROTOCOL, _RGB_CRT));
625 }
626 
EvoSORSetControl90(const NVConnectorEvoRec * pConnectorEvo,const enum nvKmsTimingsProtocol protocol,const NvU32 orIndex,const NvU32 headMask)627 static void EvoSORSetControl90(const NVConnectorEvoRec *pConnectorEvo,
628                                const enum nvKmsTimingsProtocol protocol,
629                                const NvU32 orIndex,
630                                const NvU32 headMask)
631 {
632     NVDevEvoPtr pDevEvo = pConnectorEvo->pDispEvo->pDevEvo;
633     NVEvoChannelPtr pChannel = pDevEvo->core;
634     NvU32 hwProtocol = 0;
635 
636     /* These methods should only apply to a single pDpy */
637     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
638     nvAssert(orIndex != NV_INVALID_OR);
639 
640     if (headMask != 0) {
641         switch (protocol) {
642         default:
643             nvAssert(!"unexpected protocol");
644             /* fallthrough */
645         case NVKMS_PROTOCOL_SOR_LVDS_CUSTOM:
646             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM;
647             break;
648         case NVKMS_PROTOCOL_SOR_SINGLE_TMDS_A:
649             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_A;
650             break;
651         case NVKMS_PROTOCOL_SOR_SINGLE_TMDS_B:
652             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B;
653             break;
654         case NVKMS_PROTOCOL_SOR_DUAL_TMDS:
655             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_DUAL_TMDS;
656             break;
657         case NVKMS_PROTOCOL_SOR_DP_A:
658             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_A;
659             break;
660         case NVKMS_PROTOCOL_SOR_DP_B:
661             hwProtocol = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_B;
662             break;
663         }
664     }
665 
666     nvDmaSetStartEvoMethod(pChannel, NV917D_SOR_SET_CONTROL(orIndex), 1);
667     nvDmaSetEvoMethodData(pChannel,
668         DRF_NUM(917D, _SOR_SET_CONTROL, _OWNER_MASK, headMask) |
669         DRF_NUM(917D, _SOR_SET_CONTROL, _PROTOCOL, hwProtocol) |
670         DRF_DEF(917D, _SOR_SET_CONTROL, _DE_SYNC_POLARITY, _POSITIVE_TRUE) |
671         DRF_DEF(917D, _SOR_SET_CONTROL, _PIXEL_REPLICATE_MODE, _OFF));
672 }
673 
EvoPIORSetControl90(const NVConnectorEvoRec * pConnectorEvo,const enum nvKmsTimingsProtocol protocol,const NvU32 orIndex,const NvU32 headMask)674 static void EvoPIORSetControl90(const NVConnectorEvoRec *pConnectorEvo,
675                                 const enum nvKmsTimingsProtocol protocol,
676                                 const NvU32 orIndex,
677                                 const NvU32 headMask)
678 {
679     NVDevEvoPtr pDevEvo = pConnectorEvo->pDispEvo->pDevEvo;
680     NVEvoChannelPtr pChannel = pDevEvo->core;
681 
682     /* These methods should only apply to a single pDpy */
683     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
684 
685     if (headMask != 0) {
686         nvAssert(protocol == NVKMS_PROTOCOL_PIOR_EXT_TMDS_ENC);
687     }
688 
689     nvDmaSetStartEvoMethod(pChannel, NV917D_PIOR_SET_CONTROL(orIndex), 1);
690     nvDmaSetEvoMethodData(pChannel,
691         DRF_NUM(917D, _PIOR_SET_CONTROL, _OWNER_MASK, headMask) |
692         DRF_DEF(917D, _PIOR_SET_CONTROL, _PROTOCOL, _EXT_TMDS_ENC) |
693         DRF_DEF(917D, _PIOR_SET_CONTROL, _DE_SYNC_POLARITY, _POSITIVE_TRUE));
694 }
695 
EvoGetPixelDepth90(const enum nvKmsPixelDepth pixelDepth)696 static NvU32 EvoGetPixelDepth90(const enum nvKmsPixelDepth pixelDepth)
697 {
698     switch (pixelDepth) {
699     case NVKMS_PIXEL_DEPTH_18_444:
700         return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_18_444;
701     case NVKMS_PIXEL_DEPTH_24_444:
702         return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_24_444;
703     case NVKMS_PIXEL_DEPTH_30_444:
704         return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_30_444;
705     case NVKMS_PIXEL_DEPTH_16_422:
706         return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_16_422;
707     case NVKMS_PIXEL_DEPTH_20_422:
708         return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_20_422;
709     }
710     nvAssert(!"Unexpected pixel depth");
711     return NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE_PIXEL_DEPTH_BPP_24_444;
712 }
713 
EvoHeadSetControlOR90(NVDevEvoPtr pDevEvo,const int head,const NVHwModeTimingsEvo * pTimings,const enum nvKmsPixelDepth pixelDepth,const NvBool colorSpaceOverride,NVEvoUpdateState * updateState)714 static void EvoHeadSetControlOR90(NVDevEvoPtr pDevEvo,
715                                   const int head,
716                                   const NVHwModeTimingsEvo *pTimings,
717                                   const enum nvKmsPixelDepth pixelDepth,
718                                   const NvBool colorSpaceOverride,
719                                   NVEvoUpdateState *updateState)
720 {
721     const NvU32 hwPixelDepth = EvoGetPixelDepth90(pixelDepth);
722     const NvU16 colorSpaceFlag = nvEvo1GetColorSpaceFlag(pDevEvo,
723                                                          colorSpaceOverride);
724     NVEvoChannelPtr pChannel = pDevEvo->core;
725 
726     /* These methods should only apply to a single pDpy */
727     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
728 
729     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
730 
731     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTROL_OUTPUT_RESOURCE(head), 1);
732     nvDmaSetEvoMethodData(pChannel,
733         DRF_DEF(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _CRC_MODE, _ACTIVE_RASTER) |
734         (pTimings->hSyncPol ?
735             DRF_DEF(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _HSYNC_POLARITY, _NEGATIVE_TRUE) :
736             DRF_DEF(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _HSYNC_POLARITY, _POSITIVE_TRUE)) |
737         (pTimings->vSyncPol ?
738             DRF_DEF(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _VSYNC_POLARITY, _NEGATIVE_TRUE) :
739             DRF_DEF(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _VSYNC_POLARITY, _POSITIVE_TRUE)) |
740         (colorSpaceOverride ?
741             (DRF_DEF(977D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _COLOR_SPACE_OVERRIDE, _ENABLE) |
742              DRF_NUM(977D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _COLOR_SPACE_FLAG, colorSpaceFlag)) :
743             DRF_DEF(977D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _COLOR_SPACE_OVERRIDE, _DISABLE)) |
744          DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_RESOURCE, _PIXEL_DEPTH, hwPixelDepth));
745 }
746 
EvoORSetControl90(NVDevEvoPtr pDevEvo,const NVConnectorEvoRec * pConnectorEvo,const enum nvKmsTimingsProtocol protocol,const NvU32 orIndex,const NvU32 headMask,NVEvoUpdateState * updateState)747 static void EvoORSetControl90(NVDevEvoPtr pDevEvo,
748                               const NVConnectorEvoRec *pConnectorEvo,
749                               const enum nvKmsTimingsProtocol protocol,
750                               const NvU32 orIndex,
751                               const NvU32 headMask,
752                               NVEvoUpdateState *updateState)
753 {
754     /* These methods should only apply to a single pDpy */
755     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
756 
757     nvUpdateUpdateState(pDevEvo, updateState, pDevEvo->core);
758 
759     switch (pConnectorEvo->or.type) {
760     case NV0073_CTRL_SPECIFIC_OR_TYPE_DAC:
761         EvoDACSetControl90(pConnectorEvo, protocol, orIndex, headMask);
762         break;
763     case NV0073_CTRL_SPECIFIC_OR_TYPE_SOR:
764         EvoSORSetControl90(pConnectorEvo, protocol, orIndex, headMask);
765         break;
766     case NV0073_CTRL_SPECIFIC_OR_TYPE_PIOR:
767         EvoPIORSetControl90(pConnectorEvo, protocol, orIndex, headMask);
768         break;
769     default:
770         nvAssert(!"Invalid pConnectorEvo->or.type");
771         break;
772     }
773 }
774 
EvoHeadSetDisplayId90(NVDevEvoPtr pDevEvo,const NvU32 head,const NvU32 displayId,NVEvoUpdateState * updateState)775 static void EvoHeadSetDisplayId90(NVDevEvoPtr pDevEvo,
776                                   const NvU32 head, const NvU32 displayId,
777                                   NVEvoUpdateState *updateState)
778 {
779     NVEvoChannelPtr pChannel = pDevEvo->core;
780 
781     /* These methods should only apply to a single pDpy */
782     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
783 
784     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
785 
786     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_DISPLAY_ID(head, 0), 1);
787     nvDmaSetEvoMethodData(pChannel, displayId);
788 }
789 
EvoSetUsageBounds90(NVDevEvoPtr pDevEvo,NvU32 sd,NvU32 head,const struct NvKmsUsageBounds * pUsage,NVEvoUpdateState * updateState)790 static NvBool EvoSetUsageBounds90(NVDevEvoPtr pDevEvo, NvU32 sd, NvU32 head,
791                                   const struct NvKmsUsageBounds *pUsage,
792                                   NVEvoUpdateState *updateState)
793 {
794     NVEvoChannelPtr pChannel = pDevEvo->core;
795     const NVEvoSubDevHeadStateRec *pCurrentFlipState =
796         &pDevEvo->gpus[sd].headState[head];
797     const struct NvKmsUsageBounds *pCurrentUsage =
798         &pCurrentFlipState->usage;
799     NvU64 overlayFormats = 0;
800     NvU32 baseUsage = 0, overlayUsage = 0;
801     const NVSurfaceEvoRec *pCurrentBaseSurf =
802         pCurrentFlipState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT];
803     const NVSurfaceEvoRec *pCurrentOverlaySurf =
804         pCurrentFlipState->layer[NVKMS_OVERLAY_LAYER].pSurfaceEvo[NVKMS_LEFT];
805 
806     /* These methods should only apply to a single pDpy */
807     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
808 
809     if (UsageBoundsEqual(pCurrentUsage, pUsage)) {
810         return FALSE;
811     }
812 
813     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
814 
815     /*
816      * Make sure to interlock usage bounds update with the base and overlay
817      * channel updates, otherwise it ends up violating hardware error check for
818      * the base/overlay channel blocking.
819      *
820      * // check for blocking violations
821      * for (vlt_index = 0; vlt_index < NV_CHIP_DISP_TOTAL_HEADS_PRESENT_por; vlt_index++) {
822      *   if ((wir_BlockBase[vlt_index] == TRUE)
823      *     && (wir_BaseQuiescent[vlt_index] == FALSE)
824      *     && ((ecv_GlobalHeadConnected[vlt_index] == TRUE) || (pri_ErrcheckWhenDisconnected == TRUE)))
825      *     throw (vlt_index << NV_DISP_CORE_STATE_ERROR_HEAD_INDEX_SHIFT) | NV_DISP_CORE_STATE_ERROR_001;
826      * }
827      *
828      * for (vlt_index = 0; vlt_index < NV_CHIP_DISP_TOTAL_HEADS_PRESENT_por; vlt_index++) {
829      *   if ((wir_BlockOverlay[vlt_index] == TRUE)
830      *     && (wir_OverlayQuiescent[vlt_index] == FALSE)
831      *     && ((ecv_GlobalHeadConnected[vlt_index] == TRUE) || (pri_ErrcheckWhenDisconnected == TRUE)))
832      *     throw (vlt_index << NV_DISP_CORE_STATE_ERROR_HEAD_INDEX_SHIFT) | NV_DISP_CORE_STATE_ERROR_002;
833      */
834 
835     if (pCurrentBaseSurf != NULL &&
836         !nvEvoLayerUsageBoundsEqual(pUsage, pCurrentUsage, NVKMS_MAIN_LAYER)) {
837         nvUpdateUpdateState(pDevEvo, updateState, pDevEvo->base[head]);
838     }
839 
840     if (pCurrentOverlaySurf != NULL &&
841         !nvEvoLayerUsageBoundsEqual(pUsage, pCurrentUsage, NVKMS_OVERLAY_LAYER)) {
842         nvUpdateUpdateState(pDevEvo, updateState, pDevEvo->overlay[head]);
843     }
844 
845 
846     if (pUsage->layer[NVKMS_MAIN_LAYER].usable) {
847         baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, _USABLE,
848                              _TRUE);
849 
850         if (pUsage->layer[NVKMS_MAIN_LAYER].supportedSurfaceMemoryFormats &
851             NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED8BPP) {
852             baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS,
853                                  _PIXEL_DEPTH, _BPP_64);
854         } else if (pUsage->layer[NVKMS_MAIN_LAYER].supportedSurfaceMemoryFormats &
855             NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED4BPP) {
856             baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS,
857                                  _PIXEL_DEPTH, _BPP_32);
858         } else if (pUsage->layer[NVKMS_MAIN_LAYER].supportedSurfaceMemoryFormats &
859             NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED2BPP) {
860             baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS,
861                                  _PIXEL_DEPTH, _BPP_16);
862         } else if (pUsage->layer[NVKMS_MAIN_LAYER].supportedSurfaceMemoryFormats &
863             NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED1BPP) {
864             baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS,
865                                  _PIXEL_DEPTH, _BPP_8);
866         } else {
867             nvAssert(!"Unexpected base pixel depth");
868             return FALSE;
869         }
870 
871         baseUsage |= DRF_DEF(917D, _HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS,
872                              _SUPER_SAMPLE, _X1_AA);
873     }
874 
875     overlayUsage |= pUsage->layer[NVKMS_OVERLAY_LAYER].usable ?
876         DRF_DEF(917D, _HEAD_SET_OVERLAY_USAGE_BOUNDS, _USABLE, _TRUE) :
877         DRF_DEF(917D, _HEAD_SET_OVERLAY_USAGE_BOUNDS, _USABLE, _FALSE);
878 
879     overlayFormats = pUsage->layer[NVKMS_OVERLAY_LAYER].usable ?
880         pUsage->layer[NVKMS_OVERLAY_LAYER].supportedSurfaceMemoryFormats :
881         NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED2BPP;
882 
883     if (overlayFormats & NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED4BPP) {
884         overlayUsage |= DRF_DEF(917D, _HEAD_SET_OVERLAY_USAGE_BOUNDS,
885                                 _PIXEL_DEPTH, _BPP_32);
886     } else if (overlayFormats & NVKMS_SURFACE_MEMORY_FORMATS_RGB_PACKED2BPP) {
887         overlayUsage |= DRF_DEF(917D, _HEAD_SET_OVERLAY_USAGE_BOUNDS,
888                                 _PIXEL_DEPTH, _BPP_16);
889     } else {
890         nvAssert(!"Unsupported overlay depth");
891         overlayUsage |= DRF_DEF(917D, _HEAD_SET_OVERLAY_USAGE_BOUNDS,
892                                 _PIXEL_DEPTH, _BPP_16);
893     }
894 
895     nvDmaSetStartEvoMethod(pChannel,
896             NV917D_HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS(head), 2);
897     nvDmaSetEvoMethodData(pChannel, baseUsage);
898     nvDmaSetEvoMethodData(pChannel, overlayUsage);
899 
900     return TRUE;
901 }
902 
EvoSetNotifierMethods90(NVDevEvoRec * pDevEvo,NVEvoChannelPtr pChannel,NvBool notify,NvBool awaken,NvU32 notifier)903 static void EvoSetNotifierMethods90(NVDevEvoRec *pDevEvo,
904                                     NVEvoChannelPtr pChannel,
905                                     NvBool notify,
906                                     NvBool awaken,
907                                     NvU32 notifier)
908 {
909     ASSERT_DRF_NUM(917D, _SET_NOTIFIER_CONTROL, _OFFSET, notifier);
910 
911     if (notify) {
912         NvU32 sd;
913         for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
914             if (nvPeekEvoSubDevMask(pDevEvo) & (1 << sd)) {
915                 nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
916                 nvDmaSetStartEvoMethod(pChannel,
917                     NV917D_SET_CONTEXT_DMA_NOTIFIER, 1);
918                 nvDmaSetEvoMethodData(pChannel,
919                     DRF_NUM(917D,
920                             _SET_CONTEXT_DMA_NOTIFIER,
921                             _HANDLE,
922                             pDevEvo->core->notifiersDma[sd].surfaceDesc.ctxDmaHandle));
923                 nvPopEvoSubDevMask(pDevEvo);
924             }
925         }
926     } else {
927         nvDmaSetStartEvoMethod(pChannel,
928             NV917D_SET_CONTEXT_DMA_NOTIFIER, 1);
929         nvDmaSetEvoMethodData(pChannel,
930             DRF_NUM(917D, _SET_CONTEXT_DMA_NOTIFIER, _HANDLE, 0));
931     }
932 
933     nvDmaSetStartEvoMethod(pChannel, NV917D_SET_NOTIFIER_CONTROL, 1);
934     nvDmaSetEvoMethodData(pChannel,
935         DRF_NUM(917D, _SET_NOTIFIER_CONTROL, _OFFSET, notifier) |
936         (awaken ?
937             DRF_DEF(917D, _SET_NOTIFIER_CONTROL, _MODE, _WRITE_AWAKEN) :
938             DRF_DEF(917D, _SET_NOTIFIER_CONTROL, _MODE, _WRITE)) |
939         (notify ?
940             DRF_DEF(917D, _SET_NOTIFIER_CONTROL, _NOTIFY, _ENABLE) :
941             DRF_DEF(917D, _SET_NOTIFIER_CONTROL, _NOTIFY, _DISABLE)));
942 }
943 
UpdateCore9x(NVEvoChannelPtr pChannel,NVEvoChannelMask interlockChannelMask)944 static void UpdateCore9x(NVEvoChannelPtr pChannel,
945                          NVEvoChannelMask interlockChannelMask)
946 {
947     NvU32 head, value = 0;
948 
949     ct_assert(NV_EVO_CHANNEL_MASK_BASE__SIZE ==
950               NV_EVO_CHANNEL_MASK_OVERLAY__SIZE);
951     for (head = 0; head < NV_EVO_CHANNEL_MASK_BASE__SIZE; head++) {
952         if (FLD_IDX_TEST_DRF64(_EVO, _CHANNEL_MASK, _BASE, head, _ENABLE,
953                                interlockChannelMask)) {
954             value |= DRF_IDX_DEF(917D, _UPDATE,
955                                  _INTERLOCK_WITH_BASE, head, _ENABLE);
956         }
957         if (FLD_IDX_TEST_DRF64(_EVO, _CHANNEL_MASK, _OVERLAY, head, _ENABLE,
958                                interlockChannelMask)) {
959             value |= DRF_IDX_DEF(917D, _UPDATE,
960                                  _INTERLOCK_WITH_OVERLAY, head, _ENABLE);
961         }
962     }
963 
964     nvDmaSetStartEvoMethod(pChannel, NV917D_UPDATE, 1);
965     nvDmaSetEvoMethodData(pChannel, value);
966 
967     nvDmaKickoffEvo(pChannel);
968 }
969 
UpdateBase91(NVEvoChannelPtr pChannel,NvBool interlockWithCore,NvBool vrrTearing)970 static void UpdateBase91(NVEvoChannelPtr pChannel,
971                          NvBool interlockWithCore,
972                          NvBool vrrTearing)
973 {
974     NvU32 updateValue = 0;
975     NvU32 trapParam = 0;
976 
977     if (interlockWithCore) {
978         updateValue |= DRF_DEF(917C, _UPDATE, _INTERLOCK_WITH_CORE, _ENABLE);
979     }
980 
981     nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SPARE_PRE_UPDATE_TRAP, 1);
982     nvDmaSetEvoMethodData(pChannel, trapParam);
983 
984     nvDmaSetStartEvoMethod(pChannel, NV917C_UPDATE, 1);
985     nvDmaSetEvoMethodData(pChannel, updateValue);
986 
987     nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SPARE_POST_UPDATE_TRAP, 1);
988     nvDmaSetEvoMethodData(pChannel, trapParam);
989 
990     nvDmaKickoffEvo(pChannel);
991 }
992 
UpdateOverlay9x(NVEvoChannelPtr pChannel,NvBool interlockWithCore)993 static void UpdateOverlay9x(NVEvoChannelPtr pChannel,
994                             NvBool interlockWithCore)
995 {
996     NvU32 value = 0;
997 
998     if (interlockWithCore) {
999         value |= DRF_DEF(917E, _UPDATE, _INTERLOCK_WITH_CORE, _ENABLE);
1000     }
1001 
1002     nvDmaSetStartEvoMethod(pChannel, NV917E_UPDATE, 1);
1003     nvDmaSetEvoMethodData(pChannel, value);
1004 
1005     nvDmaKickoffEvo(pChannel);
1006 }
1007 
EvoUpdate91(NVDevEvoPtr pDevEvo,const NVEvoUpdateState * updateState,NvBool releaseElv)1008 static void EvoUpdate91(NVDevEvoPtr pDevEvo,
1009                         const NVEvoUpdateState *updateState,
1010                         NvBool releaseElv)
1011 {
1012     NvU32 sd;
1013     NVEvoChannelMask fliplockedBaseChannels[NVKMS_MAX_SUBDEVICES] = { };
1014     NvBool updateAllFliplockedBaseChannels = FALSE;
1015 
1016     /*
1017      * Multiple 'base + core channel interlocked' updates can create deadlock
1018      * if heads are flip locked.
1019      *
1020      * For example - if head-0 and head-1 are flip locked and you initiate two
1021      * 'base + core channel interlocked' updates separately for each of
1022      * the head then that creates deadlock:
1023      *
1024      *
1025      *      +--------+      +--------+      +--------+
1026      *      | BASE-0 |      |  CORE  |      | BASE-1 |
1027      *      +--------+      +--------+      +--------+
1028      *      |        |      |        |      |        |
1029      *      |        |      |        |      |        |
1030      *      +--------+------+--------+      |        |
1031      *      |      INTERLOCKED       |      |        |
1032      *      |        UPDATE-0        |      |        |
1033      *      +--------+------+--------+      |        |
1034      *      | Base   |      | Core   |      |        |
1035      *  <...| update |<.... | Update |      |        |
1036      *  :   | for    |      | for    |      |        |
1037      *  :   | head-0 |      | head-0 |      |        |
1038      *  :   +--------+------+--------+      |        |
1039      *  :   |        |      |   ^    |      |        |
1040      *  :   |        |      |   :    |      |        |
1041      *  :   +--------+      |   :    |      |        |
1042      *  :                   |   :    |      |        |
1043      *  :                   +---(----+------+--------+
1044      *  :                   |   :  INTERLOCKED       |
1045      *  :                   |   :    UPDATE-1        |
1046      *  :                   +--------+------+--------+
1047      *  V                   | Core   |      | Base   |
1048      *  :                   | update |<.... | Update |
1049      *  :                   | for    |      | for    |<...
1050      *  :                   | head-1 |      | head-1 |   :
1051      *  :                   +--------+------+--------+   :
1052      *  :                   |        |      |        |   ^
1053      *  :                   +--------+      +--------+   :
1054      *  :                                                :
1055      *  V...................>............................>
1056      *
1057      *            ^
1058      *            |
1059      *            |
1060      *  [ BASE-0 and BASE-1 are fliplocked ]
1061      *
1062      * Here you can follow the dotted arrow line and see how deadlock
1063      * has been formed. The dotted arrow line indicates the execution
1064      * dependency of the one update onto another, e.g. the core update
1065      * for head-1 can't get executed unless the core update for head-0
1066      * gets executed.
1067      *
1068      * To prevent this deadlock, initiate the base channel updates for all flip
1069      * locked heads if update state contains 'base + core channel interlocked'
1070      * for the flip locked head.
1071      */
1072     for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
1073         NVEvoChannelMask updateChannelMask = updateState->subdev[sd].channelMask;
1074         NVEvoChannelMask interlockChannelMask =
1075             updateChannelMask & ~updateState->subdev[sd].noCoreInterlockMask;
1076         NvU32 head;
1077 
1078         for (head = 0; head < NV_EVO_CHANNEL_MASK_BASE__SIZE; head++) {
1079             NVEvoChannelMask thisMask =
1080                 DRF_IDX_DEF64(_EVO, _CHANNEL_MASK, _BASE, head, _ENABLE);
1081             NVEvoSubDevPtr pEvoSubDev = &pDevEvo->gpus[sd];
1082             NVEvoHeadControlPtr pHC = &pEvoSubDev->headControl[head];
1083 
1084             if (pHC->flipLock) {
1085                 fliplockedBaseChannels[sd] |= thisMask;
1086             }
1087 
1088             /*
1089              * If this update is updating only one base channel without any core
1090              * interlock, in that case, we don't need to also update all flip
1091              * locked base channels.
1092              */
1093             if (NV_EVO_CHANNEL_MASK_POPCOUNT(interlockChannelMask) <= 1 &&
1094                 !FLD_TEST_DRF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE,
1095                                 updateChannelMask)) {
1096                 continue;
1097             }
1098 
1099             if ((updateChannelMask & thisMask) != 0x0 && pHC->flipLock) {
1100                 updateAllFliplockedBaseChannels = TRUE;
1101             }
1102         }
1103     }
1104 
1105     for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
1106         NVEvoChannelMask updateChannelMask = updateState->subdev[sd].channelMask |
1107             (updateAllFliplockedBaseChannels ? fliplockedBaseChannels[sd] : 0x0);
1108         NVEvoChannelMask interlockChannelMask =
1109             updateChannelMask & ~updateState->subdev[sd].noCoreInterlockMask;
1110         NvBool interlockWithCore = FALSE;
1111         const NvU32 subDeviceMask = (1 << sd);
1112         NvU32 head;
1113 
1114         nvPushEvoSubDevMask(pDevEvo, subDeviceMask);
1115 
1116         if (NV_EVO_CHANNEL_MASK_POPCOUNT(interlockChannelMask) > 1) {
1117             /* We can only interlock updates if core is included. */
1118             nvAssert(!FLD_TEST_DRF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE,
1119                                      updateState->subdev[sd].noCoreInterlockMask));
1120             updateChannelMask |= DRF_DEF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE);
1121             interlockChannelMask |=
1122                 DRF_DEF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE);
1123             interlockWithCore = TRUE;
1124         }
1125 
1126         if (FLD_TEST_DRF64(_EVO, _CHANNEL_MASK, _CORE, _ENABLE,
1127                            updateChannelMask)) {
1128             UpdateCore9x(pDevEvo->core, updateChannelMask);
1129         }
1130 
1131         for (head = 0; head < NV_EVO_CHANNEL_MASK_OVERLAY__SIZE; head++) {
1132             NVEvoChannelMask thisMask =
1133                 DRF_IDX_DEF64(_EVO, _CHANNEL_MASK, _OVERLAY, head, _ENABLE);
1134             if (updateChannelMask & thisMask) {
1135                 NvBool thisInterlockWithCore = interlockWithCore &&
1136                     (interlockChannelMask & thisMask);
1137                 UpdateOverlay9x(pDevEvo->overlay[head],
1138                                 thisInterlockWithCore);
1139             }
1140         }
1141 
1142         for (head = 0; head < NV_EVO_CHANNEL_MASK_BASE__SIZE; head++) {
1143             NVEvoChannelMask thisMask =
1144                 DRF_IDX_DEF64(_EVO, _CHANNEL_MASK, _BASE, head, _ENABLE);
1145             if (updateChannelMask & thisMask) {
1146                 NvBool thisInterlockWithCore = interlockWithCore &&
1147                     (interlockChannelMask & thisMask);
1148                 NvBool vrrTearing =
1149                     updateState->subdev[sd].base[head].vrrTearing;
1150 
1151                 UpdateBase91(pDevEvo->base[head],
1152                              thisInterlockWithCore, vrrTearing);
1153             }
1154         }
1155 
1156         nvPopEvoSubDevMask(pDevEvo);
1157     }
1158 }
1159 
EvoSetNotifier90(NVDevEvoRec * pDevEvo,const NvBool notify,const NvBool awaken,const NvU32 notifier,NVEvoUpdateState * updateState)1160 static void EvoSetNotifier90(NVDevEvoRec *pDevEvo,
1161                              const NvBool notify,
1162                              const NvBool awaken,
1163                              const NvU32 notifier,
1164                              NVEvoUpdateState *updateState)
1165 {
1166     /* These methods should only apply to a single subdevice */
1167     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
1168 
1169     nvUpdateUpdateState(pDevEvo, updateState, pDevEvo->core);
1170 
1171     EvoSetNotifierMethods90(pDevEvo, pDevEvo->core, notify, awaken, notifier);
1172 }
1173 
1174 /*
1175  * Returns the data for the SET_STORAGE method.  The method data
1176  * format is the same between classes 90[CDE].
1177  */
EvoComputeSetStorage90(const NVDevEvoRec * pDevEvo,const NVSurfaceEvoRec * pSurfaceEvo)1178 static NvU32 EvoComputeSetStorage90(const NVDevEvoRec *pDevEvo,
1179                                     const NVSurfaceEvoRec *pSurfaceEvo)
1180 {
1181     NvU32 setStorage;
1182 
1183     NvU32 pitch = nvEvoGetHeadSetStoragePitchValue(
1184                     pDevEvo,
1185                     pSurfaceEvo->layout,
1186                     pSurfaceEvo->planes[0].pitch);
1187     nvAssert(pitch != 0);
1188 
1189     if (pSurfaceEvo->layout == NvKmsSurfaceMemoryLayoutBlockLinear) {
1190         // 1 block = 1 * X Gobs; 1 Gob = 64B * 4Lines; X = 1 <<
1191         // blockHeightLog2Gobs
1192         NvU32 blockHeight = pSurfaceEvo->log2GobsPerBlockY;
1193 
1194         setStorage = DRF_NUM(917D, _HEAD_SET_STORAGE, _BLOCK_HEIGHT, blockHeight) |
1195                      DRF_DEF(917D, _HEAD_SET_STORAGE, _MEMORY_LAYOUT, _BLOCKLINEAR);
1196     } else {
1197         setStorage = DRF_DEF(917D, _HEAD_SET_STORAGE, _MEMORY_LAYOUT, _PITCH);
1198     }
1199 
1200     ASSERT_DRF_NUM(917D, _HEAD_SET_STORAGE, _PITCH, pitch);
1201     setStorage |= DRF_NUM(917D, _HEAD_SET_STORAGE, _PITCH, pitch);
1202 
1203     return setStorage;
1204 }
1205 
SetCscMatrix(NVEvoChannelPtr pChannel,NvU32 method,const struct NvKmsCscMatrix * matrix,NvU32 extraFirstWordBits)1206 static void SetCscMatrix(NVEvoChannelPtr pChannel, NvU32 method,
1207                          const struct NvKmsCscMatrix *matrix,
1208                          NvU32 extraFirstWordBits)
1209 {
1210     int y;
1211 
1212     // The _COEFF fields are the same across all of the methods on all
1213     // channels.
1214     ct_assert(DRF_SHIFTMASK(NV917C_SET_CSC_RED2RED_COEFF) ==
1215               DRF_SHIFTMASK(NV917D_HEAD_SET_CSC_RED2RED_COEFF));
1216     ct_assert(DRF_SHIFTMASK(NV917C_SET_CSC_RED2RED_COEFF) ==
1217               DRF_SHIFTMASK(NV917E_SET_CSC_RED2RED_COEFF));
1218 
1219     for (y = 0; y < 3; y++) {
1220         int x;
1221 
1222         for (x = 0; x < 4; x++) {
1223             // Use DRF_NUM to truncate client-supplied values that are out of
1224             // range.
1225             NvU32 val = DRF_NUM(917C, _SET_CSC_RED2RED, _COEFF,
1226                                 matrix->m[y][x]);
1227 
1228             if (x == 0 && y == 0) {
1229                 val |= extraFirstWordBits;
1230             }
1231 
1232             nvDmaSetStartEvoMethod(pChannel, method, 1);
1233             nvDmaSetEvoMethodData(pChannel, val);
1234 
1235             method += 4;
1236         }
1237     }
1238 }
1239 
1240 /*
1241  * These values are the same between all base
1242  * (_SURFACE_SET_PARAMS_FORMAT_) and core (_HEAD_SET_PARAMS_FORMAT_)
1243  * EVO classes.
1244  *
1245  * Return 0 in the case of an unrecognized NvKmsSurfaceMemoryFormat.
1246  */
nvHwFormatFromKmsFormat90(const enum NvKmsSurfaceMemoryFormat format)1247 static NvU32 nvHwFormatFromKmsFormat90(
1248     const enum NvKmsSurfaceMemoryFormat format)
1249 {
1250     switch (format) {
1251     case NvKmsSurfaceMemoryFormatI8:
1252         return NV917D_HEAD_SET_PARAMS_FORMAT_I8;
1253     case NvKmsSurfaceMemoryFormatA1R5G5B5:
1254     case NvKmsSurfaceMemoryFormatX1R5G5B5:
1255         return NV917D_HEAD_SET_PARAMS_FORMAT_A1R5G5B5;
1256     case NvKmsSurfaceMemoryFormatR5G6B5:
1257         return NV917D_HEAD_SET_PARAMS_FORMAT_R5G6B5;
1258     case NvKmsSurfaceMemoryFormatA8R8G8B8:
1259     case NvKmsSurfaceMemoryFormatX8R8G8B8:
1260         return NV917D_HEAD_SET_PARAMS_FORMAT_A8R8G8B8;
1261     case NvKmsSurfaceMemoryFormatA8B8G8R8:
1262     case NvKmsSurfaceMemoryFormatX8B8G8R8:
1263         return NV917D_HEAD_SET_PARAMS_FORMAT_A8B8G8R8;
1264     case NvKmsSurfaceMemoryFormatA2B10G10R10:
1265     case NvKmsSurfaceMemoryFormatX2B10G10R10:
1266         return NV917D_HEAD_SET_PARAMS_FORMAT_A2B10G10R10;
1267     case NvKmsSurfaceMemoryFormatRF16GF16BF16AF16:
1268     case NvKmsSurfaceMemoryFormatRF16GF16BF16XF16:
1269         return NV917D_HEAD_SET_PARAMS_FORMAT_RF16_GF16_BF16_AF16;
1270     case NvKmsSurfaceMemoryFormatR16G16B16A16:
1271         return NV917D_HEAD_SET_PARAMS_FORMAT_R16_G16_B16_A16;
1272     case NvKmsSurfaceMemoryFormatRF32GF32BF32AF32:
1273     case NvKmsSurfaceMemoryFormatY8_U8__Y8_V8_N422:
1274     case NvKmsSurfaceMemoryFormatU8_Y8__V8_Y8_N422:
1275     case NvKmsSurfaceMemoryFormatY8___U8V8_N444:
1276     case NvKmsSurfaceMemoryFormatY8___V8U8_N444:
1277     case NvKmsSurfaceMemoryFormatY8___U8V8_N422:
1278     case NvKmsSurfaceMemoryFormatY8___V8U8_N422:
1279     case NvKmsSurfaceMemoryFormatY8___U8V8_N420:
1280     case NvKmsSurfaceMemoryFormatY8___V8U8_N420:
1281     case NvKmsSurfaceMemoryFormatY10___U10V10_N444:
1282     case NvKmsSurfaceMemoryFormatY10___V10U10_N444:
1283     case NvKmsSurfaceMemoryFormatY10___U10V10_N422:
1284     case NvKmsSurfaceMemoryFormatY10___V10U10_N422:
1285     case NvKmsSurfaceMemoryFormatY10___U10V10_N420:
1286     case NvKmsSurfaceMemoryFormatY10___V10U10_N420:
1287     case NvKmsSurfaceMemoryFormatY12___U12V12_N444:
1288     case NvKmsSurfaceMemoryFormatY12___V12U12_N444:
1289     case NvKmsSurfaceMemoryFormatY12___U12V12_N422:
1290     case NvKmsSurfaceMemoryFormatY12___V12U12_N422:
1291     case NvKmsSurfaceMemoryFormatY12___U12V12_N420:
1292     case NvKmsSurfaceMemoryFormatY12___V12U12_N420:
1293     case NvKmsSurfaceMemoryFormatY8___U8___V8_N444:
1294     case NvKmsSurfaceMemoryFormatY8___U8___V8_N420:
1295         return 0;
1296     }
1297 
1298     return 0;
1299 }
1300 
EvoSetSurface(NVDevEvoPtr pDevEvo,const int head,const NVSurfaceEvoRec * pSurfaceEvo,const struct NvKmsCscMatrix * pCscMatrix,NVEvoUpdateState * updateState)1301 static void EvoSetSurface(NVDevEvoPtr pDevEvo,
1302                           const int head,
1303                           const NVSurfaceEvoRec *pSurfaceEvo,
1304                           const struct NvKmsCscMatrix *pCscMatrix,
1305                           NVEvoUpdateState *updateState)
1306 {
1307     NVEvoChannelPtr pChannel = pDevEvo->core;
1308     NvU32 sd;
1309 
1310     /* These methods should only apply to a single pDpy */
1311     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
1312 
1313     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
1314 
1315     FOR_EACH_SUBDEV_IN_MASK(sd, nvPeekEvoSubDevMask(pDevEvo)) {
1316         /*
1317          * The EVO2 ->SetCursorImage() function programs cursor image surface
1318          * only if NVEvoSubDeviceRec::pCoreChannelSurface is non-null.
1319          */
1320         pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head] = pSurfaceEvo;
1321     } FOR_EACH_SUBDEV_IN_MASK_END
1322 
1323     if (!pSurfaceEvo) {
1324         // Disable surface scanout on this head.  It will scan out the default
1325         // base color instead.
1326         nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTEXT_DMAS_ISO(head), 1);
1327         nvDmaSetEvoMethodData(pChannel, 0);
1328         return;
1329     }
1330 
1331     nvAssert(pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1332 
1333     // XXX[AGP]: These methods are sequential, but sending them with a single
1334     // count=7 method header sometimes causes EVO to throw an IsoViolation
1335     // exception.
1336 
1337     // Set the surface parameters.
1338     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_OFFSET(head), 1);
1339     nvDmaSetEvoMethodData(pChannel,
1340         nvCtxDmaOffsetFromBytes(pSurfaceEvo->planes[0].offset));
1341 
1342     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_SIZE(head), 1);
1343     nvDmaSetEvoMethodData(pChannel,
1344         DRF_NUM(917D, _HEAD_SET_SIZE, _WIDTH, pSurfaceEvo->widthInPixels) |
1345         DRF_NUM(917D, _HEAD_SET_SIZE, _HEIGHT, pSurfaceEvo->heightInPixels));
1346 
1347     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_STORAGE(head), 1);
1348     nvDmaSetEvoMethodData(pChannel, EvoComputeSetStorage90(pDevEvo, pSurfaceEvo));
1349 
1350     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PARAMS(head), 1);
1351     nvDmaSetEvoMethodData(pChannel,
1352         DRF_NUM(917D, _HEAD_SET_PARAMS, _FORMAT,
1353         nvHwFormatFromKmsFormat90(pSurfaceEvo->format)) |
1354         DRF_DEF(917D, _HEAD_SET_PARAMS, _SUPER_SAMPLE, _X1_AA) |
1355         DRF_DEF(917D, _HEAD_SET_PARAMS, _GAMMA, _LINEAR));
1356 
1357     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTEXT_DMAS_ISO(head), 1);
1358     nvDmaSetEvoMethodData(pChannel, pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1359 
1360     /* NULL => don't change the CSC. */
1361     if (pCscMatrix) {
1362         SetCscMatrix(pChannel, NV917D_HEAD_SET_CSC_RED2RED(head), pCscMatrix, 0);
1363     }
1364 }
1365 
1366 static void
EvoPushSetCoreSurfaceMethodsForOneSd(NVDevEvoRec * pDevEvo,const NvU32 sd,const int head,const NVSurfaceEvoRec * pSurfaceEvo,const struct NvKmsCscMatrix * pCscMatrix,NVEvoUpdateState * updateState)1367 EvoPushSetCoreSurfaceMethodsForOneSd(NVDevEvoRec *pDevEvo,
1368                                      const NvU32 sd,
1369                                      const int head,
1370                                      const NVSurfaceEvoRec *pSurfaceEvo,
1371                                      const struct NvKmsCscMatrix *pCscMatrix,
1372                                      NVEvoUpdateState *updateState)
1373 {
1374     const NVEvoSubDevHeadStateRec *pSdHeadState =
1375                                    &pDevEvo->gpus[sd].headState[head];
1376     const NVFlipCursorEvoHwState *pSdCursorState = &pSdHeadState->cursor;
1377 
1378     const NVDispEvoRec *pDispEvo = pDevEvo->gpus[sd].pDispEvo;
1379     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
1380 
1381     NvBool  enableOutputLut = pHeadState->lut.outputLutEnabled;
1382     NvBool  enableBaseLut = pHeadState->lut.baseLutEnabled;
1383 
1384     NVLutSurfaceEvoPtr pCurLutSurfEvo = pHeadState->lut.pCurrSurface;
1385     NvU32 lutCtxdma = pCurLutSurfEvo != NULL ?
1386         pCurLutSurfEvo->surfaceDesc.ctxDmaHandle : 0x0;
1387 
1388     if (pSurfaceEvo == NULL || pCurLutSurfEvo == NULL) {
1389         enableOutputLut = FALSE;
1390         enableBaseLut = FALSE;
1391         lutCtxdma = 0x0;
1392     }
1393 
1394     nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
1395 
1396     EvoSetSurface(pDevEvo, head, pSurfaceEvo, pCscMatrix, updateState);
1397 
1398     EvoSetCursorImage(pDevEvo,
1399                       head,
1400                       pSurfaceEvo != NULL ?
1401                           pSdCursorState->pSurfaceEvo : NULL,
1402                       updateState,
1403                       &pSdCursorState->cursorCompParams);
1404 
1405     /*
1406      * EvoPushSetLUTContextDmaMethodsForOneSd() force enables base
1407      * Lut if core scanout surface depth is 8.
1408      */
1409     EvoPushSetLUTContextDmaMethodsForOneSd(
1410         pDevEvo, sd, head, lutCtxdma, enableBaseLut, enableOutputLut,
1411         updateState);
1412 
1413     nvPopEvoSubDevMask(pDevEvo);
1414 }
1415 
1416 static void
FlipBase90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,const NVFlipChannelEvoHwState * pHwState,NVEvoUpdateState * updateState)1417 FlipBase90(NVDevEvoPtr pDevEvo,
1418            NVEvoChannelPtr pChannel,
1419            const NVFlipChannelEvoHwState *pHwState,
1420            NVEvoUpdateState *updateState)
1421 {
1422     int eye;
1423 
1424     /* program notifier */
1425 
1426     if (pHwState->completionNotifier.surface.pSurfaceEvo == NULL) {
1427 
1428         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMA_NOTIFIER, 1);
1429         nvDmaSetEvoMethodData(pChannel, 0);
1430         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_NOTIFIER_CONTROL, 1);
1431         nvDmaSetEvoMethodData(pChannel, 0);
1432 
1433     } else {
1434         const NVFlipNIsoSurfaceEvoHwState *pNIso =
1435             &pHwState->completionNotifier.surface;
1436         NvU32 value = 0;
1437 
1438         if (pNIso->format == NVKMS_NISO_FORMAT_LEGACY) {
1439             value = FLD_SET_DRF(917C, _SET_NOTIFIER_CONTROL, _FORMAT,
1440                                 _LEGACY, value);
1441         } else {
1442             value = FLD_SET_DRF(917C, _SET_NOTIFIER_CONTROL, _FORMAT,
1443                                 _FOUR_WORD, value);
1444         }
1445 
1446         value = FLD_SET_DRF_NUM(917C, _SET_NOTIFIER_CONTROL, _OFFSET,
1447                                 pNIso->offsetInWords, value);
1448 
1449         value = FLD_SET_DRF_NUM(917C, _SET_NOTIFIER_CONTROL, _MODE,
1450                                 pHwState->completionNotifier.awaken ?
1451                                 NV917C_SET_NOTIFIER_CONTROL_MODE_WRITE_AWAKEN :
1452                                 NV917C_SET_NOTIFIER_CONTROL_MODE_WRITE, value);
1453 
1454         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMA_NOTIFIER, 1);
1455         nvDmaSetEvoMethodData(pChannel, pNIso->pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1456 
1457         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_NOTIFIER_CONTROL, 1);
1458         nvDmaSetEvoMethodData(pChannel, value);
1459     }
1460 
1461     /* program semaphore */
1462     nvAssertSameSemaphoreSurface(pHwState);
1463 
1464     if (pHwState->syncObject.u.semaphores.acquireSurface.pSurfaceEvo == NULL) {
1465 
1466         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMA_SEMAPHORE, 1);
1467         nvDmaSetEvoMethodData(pChannel, 0);
1468 
1469         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_CONTROL, 1);
1470         nvDmaSetEvoMethodData(pChannel, 0);
1471 
1472         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_ACQUIRE, 1);
1473         nvDmaSetEvoMethodData(pChannel, 0);
1474 
1475         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_RELEASE, 1);
1476         nvDmaSetEvoMethodData(pChannel, 0);
1477     } else {
1478         const NVFlipNIsoSurfaceEvoHwState *pNIso =
1479             &pHwState->syncObject.u.semaphores.acquireSurface;
1480         NvU32 value = 0;
1481 
1482         if (pNIso->format == NVKMS_NISO_FORMAT_LEGACY) {
1483             value = FLD_SET_DRF(917C, _SET_SEMAPHORE_CONTROL, _FORMAT,
1484                                 _LEGACY, value);
1485         } else {
1486             value = FLD_SET_DRF(917C, _SET_SEMAPHORE_CONTROL, _FORMAT,
1487                                 _FOUR_WORD, value);
1488         }
1489 
1490         value = FLD_SET_DRF_NUM(917C, _SET_SEMAPHORE_CONTROL, _OFFSET,
1491                                 pNIso->offsetInWords, value);
1492 
1493         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMA_SEMAPHORE, 1);
1494         nvDmaSetEvoMethodData(pChannel, pNIso->pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1495 
1496         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_ACQUIRE, 1);
1497         nvDmaSetEvoMethodData(pChannel,
1498             pHwState->syncObject.u.semaphores.acquireValue);
1499 
1500         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_RELEASE, 1);
1501         nvDmaSetEvoMethodData(pChannel,
1502             pHwState->syncObject.u.semaphores.releaseValue);
1503 
1504         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_SEMAPHORE_CONTROL, 1);
1505         nvDmaSetEvoMethodData(pChannel, value);
1506     }
1507 
1508     if (!pHwState->pSurfaceEvo[NVKMS_LEFT]) {
1509         nvAssert(!pHwState->pSurfaceEvo[NVKMS_RIGHT]);
1510 
1511         // Disable base on this head.
1512         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMAS_ISO(0), 1);
1513         nvDmaSetEvoMethodData(pChannel, 0);
1514 
1515         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMAS_ISO(1), 1);
1516         nvDmaSetEvoMethodData(pChannel, 0);
1517 
1518         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_PRESENT_CONTROL, 1);
1519         nvDmaSetEvoMethodData(pChannel, 0);
1520 
1521         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CSC_RED2RED, 1);
1522         nvDmaSetEvoMethodData(pChannel, DRF_DEF(917C, _SET_CSC_RED2RED, _OWNER, _CORE));
1523         return;
1524     }
1525 
1526     NvU32 presentControl =
1527         DRF_NUM(917C, _SET_PRESENT_CONTROL, _MIN_PRESENT_INTERVAL,
1528                 pHwState->minPresentInterval);
1529 
1530     if (pHwState->tearing) {
1531         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL, _BEGIN_MODE,
1532                                      _IMMEDIATE, presentControl);
1533         /*
1534          * This avoids an invalid state exception:
1535          *
1536          * if ((SetPresentControl.BeginMode != NON_TEARING) &&
1537          *     (SetPresentControl.BeginMode != AT_FRAME)
1538          *   && (wir_InterlockWithCore == ENABLE))
1539          *   throw NV_DISP_BASE_STATE_ERROR_001;
1540          */
1541         nvDisableCoreInterlockUpdateState(pDevEvo, updateState, pChannel);
1542     } else {
1543         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL, _BEGIN_MODE,
1544                                      _NON_TEARING, presentControl);
1545     }
1546 
1547     if (pHwState->pSurfaceEvo[NVKMS_RIGHT]) {
1548         if (pHwState->perEyeStereoFlip) {
1549             presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1550                                          _STEREO_FLIP_MODE, _AT_ANY_FRAME,
1551                                          presentControl);
1552         } else {
1553             presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1554                                          _STEREO_FLIP_MODE, _PAIR_FLIP,
1555                                          presentControl);
1556         }
1557         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1558                                      _MODE, _STEREO, presentControl);
1559     } else {
1560         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1561                                      _MODE, _MONO, presentControl);
1562     }
1563 
1564     // If we have a non-zero timestamp we need to enable timestamp mode
1565     if (pHwState->timeStamp == 0) {
1566         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1567                                      _TIMESTAMP_MODE, _DISABLE, presentControl);
1568     } else {
1569         presentControl = FLD_SET_DRF(917C, _SET_PRESENT_CONTROL,
1570                                      _TIMESTAMP_MODE, _ENABLE, presentControl);
1571     }
1572 
1573     nvDmaSetStartEvoMethod(pChannel, NV917C_SET_TIMESTAMP_ORIGIN_LO, 2);
1574     nvDmaSetEvoMethodData(pChannel, 0);
1575     nvDmaSetEvoMethodData(pChannel, 0);
1576 
1577     nvDmaSetStartEvoMethod(pChannel, NV917C_SET_UPDATE_TIMESTAMP_LO, 2);
1578     nvDmaSetEvoMethodData(pChannel, NvU64_LO32(pHwState->timeStamp));
1579     nvDmaSetEvoMethodData(pChannel, NvU64_HI32(pHwState->timeStamp));
1580 
1581     nvDmaSetStartEvoMethod(pChannel, NV917C_SET_PRESENT_CONTROL, 1);
1582     nvDmaSetEvoMethodData(pChannel, presentControl);
1583 
1584     SetCscMatrix(pChannel, NV917C_SET_CSC_RED2RED, &pHwState->cscMatrix,
1585                  DRF_DEF(917C, _SET_CSC_RED2RED, _OWNER, _BASE));
1586 
1587     // Set the surface parameters.
1588     FOR_ALL_EYES(eye) {
1589         NvU32 ctxdma = 0;
1590         NvU64 offset = 0;
1591 
1592         if (pHwState->pSurfaceEvo[eye]) {
1593             ctxdma = pHwState->pSurfaceEvo[eye]->planes[0].surfaceDesc.ctxDmaHandle;
1594             offset = pHwState->pSurfaceEvo[eye]->planes[0].offset;
1595         }
1596 
1597         nvDmaSetStartEvoMethod(pChannel, NV917C_SURFACE_SET_OFFSET(0, eye), 1);
1598         nvDmaSetEvoMethodData(pChannel,
1599             DRF_NUM(917C, _SURFACE_SET_OFFSET, _ORIGIN,
1600                     nvCtxDmaOffsetFromBytes(offset)));
1601 
1602         nvDmaSetStartEvoMethod(pChannel, NV917C_SET_CONTEXT_DMAS_ISO(eye), 1);
1603         nvDmaSetEvoMethodData(pChannel, ctxdma);
1604     }
1605 
1606     ASSERT_EYES_MATCH(pHwState->pSurfaceEvo, widthInPixels);
1607     ASSERT_EYES_MATCH(pHwState->pSurfaceEvo, heightInPixels);
1608     nvDmaSetStartEvoMethod(pChannel, NV917C_SURFACE_SET_SIZE(0), 1);
1609     nvDmaSetEvoMethodData(pChannel,
1610         DRF_NUM(917C, _SURFACE_SET_SIZE, _WIDTH,
1611                 pHwState->pSurfaceEvo[NVKMS_LEFT]->widthInPixels) |
1612         DRF_NUM(917C, _SURFACE_SET_SIZE, _HEIGHT,
1613                 pHwState->pSurfaceEvo[NVKMS_LEFT]->heightInPixels));
1614 
1615     nvAssert(pHwState->sizeIn.width == pHwState->pSurfaceEvo[NVKMS_LEFT]->widthInPixels);
1616     nvAssert(pHwState->sizeIn.height == pHwState->pSurfaceEvo[NVKMS_LEFT]->heightInPixels);
1617     nvAssert(pHwState->sizeIn.width == pHwState->sizeOut.width);
1618     nvAssert(pHwState->sizeIn.height == pHwState->sizeOut.height);
1619 
1620     nvAssert(!pHwState->pSurfaceEvo[NVKMS_RIGHT] ||
1621              (EvoComputeSetStorage90(pDevEvo, pHwState->pSurfaceEvo[NVKMS_LEFT]) ==
1622               EvoComputeSetStorage90(pDevEvo, pHwState->pSurfaceEvo[NVKMS_RIGHT])));
1623     nvDmaSetStartEvoMethod(pChannel, NV917C_SURFACE_SET_STORAGE(0), 1);
1624     nvDmaSetEvoMethodData(pChannel, EvoComputeSetStorage90(pDevEvo, pHwState->pSurfaceEvo[NVKMS_LEFT]));
1625 
1626     ASSERT_EYES_MATCH(pHwState->pSurfaceEvo, format);
1627     nvDmaSetStartEvoMethod(pChannel, NV917C_SURFACE_SET_PARAMS(0), 1);
1628     nvDmaSetEvoMethodData(pChannel,
1629         DRF_NUM(917C, _SURFACE_SET_PARAMS, _FORMAT,
1630         nvHwFormatFromKmsFormat90(pHwState->pSurfaceEvo[NVKMS_LEFT]->format)) |
1631         DRF_DEF(917C, _SURFACE_SET_PARAMS, _SUPER_SAMPLE, _X1_AA) |
1632         DRF_DEF(917C, _SURFACE_SET_PARAMS, _GAMMA, _LINEAR));
1633 
1634     nvAssert(pHwState->inputLut.pLutSurfaceEvo == NULL);
1635 }
1636 
1637 static void
FlipOverlay90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,const NVFlipChannelEvoHwState * pHwState,NvBool * pInterlockwithCore)1638 FlipOverlay90(NVDevEvoPtr pDevEvo,
1639               NVEvoChannelPtr pChannel,
1640               const NVFlipChannelEvoHwState *pHwState,
1641               NvBool *pInterlockwithCore)
1642 {
1643     const NvU32 head =
1644         NV_EVO_CHANNEL_MASK_BASE_HEAD_NUMBER(pChannel->channelMask);
1645     const NVSurfaceEvoRec *pSurfaceEvo = pHwState->pSurfaceEvo[NVKMS_LEFT];
1646     NvU32 value;
1647     NvU32 sd;
1648 
1649     /* Overlay class 917E can't do stereo */
1650     nvAssert(!pHwState->pSurfaceEvo[NVKMS_RIGHT]);
1651 
1652     /*
1653      * The NVKMS driver enforces these conditions on its clients: 1) enable a
1654      * core-surface before enabling an overlay-surface, 2) disable an
1655      * overlay-surface before disabling a core-surface.
1656      *
1657      * Updates to enable/disable a core and an overlay surface execute
1658      * separately and are not interlocked. To avoid a race condition between a
1659      * core and an overlay channel, detect an overlay channel update which is
1660      * enabling/disabling an overlay-surface and interlock that update with a
1661      * core channel update.
1662      *
1663      * This makes sure that an update to disable an overlay-surface interlocked
1664      * with a core channel and a follow-on update to disable the core-surface
1665      * will wait for the previous overlay flip to complete. It also makes sure
1666      * that an update to enable an overlay-surface will wait for the previous
1667      * core channel flip to complete.
1668      */
1669 
1670     FOR_EACH_SUBDEV_IN_MASK(sd, nvPeekEvoSubDevMask(pDevEvo)) {
1671         NvBool prevCtxDmaIso =
1672             pDevEvo->pSubDevices[sd]->overlayContextDmaIso[head];
1673 
1674         if ((prevCtxDmaIso != 0x0 && pSurfaceEvo == NULL) ||
1675             (prevCtxDmaIso == 0x0 && pSurfaceEvo != NULL)) {
1676             *pInterlockwithCore = TRUE;
1677         }
1678 
1679         if (pSurfaceEvo != NULL) {
1680             pDevEvo->pSubDevices[sd]->overlayContextDmaIso[head] =
1681                 pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle;
1682             pDevEvo->pSubDevices[sd]->overlaySurfFormat[head] = pSurfaceEvo->format;
1683 
1684         } else {
1685             pDevEvo->pSubDevices[sd]->overlayContextDmaIso[head] = 0x0;
1686         }
1687     } FOR_EACH_SUBDEV_IN_MASK_END
1688 
1689     /* program notifier */
1690 
1691     if (pHwState->completionNotifier.surface.pSurfaceEvo == NULL) {
1692 
1693         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMA_NOTIFIER, 1);
1694         nvDmaSetEvoMethodData(pChannel, 0);
1695         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_NOTIFIER_CONTROL, 1);
1696         nvDmaSetEvoMethodData(pChannel, 0);
1697 
1698     } else {
1699         const NVFlipNIsoSurfaceEvoHwState *pNIso =
1700             &pHwState->completionNotifier.surface;
1701         value = 0;
1702 
1703         if (pNIso->format == NVKMS_NISO_FORMAT_LEGACY) {
1704             value = FLD_SET_DRF(917E, _SET_NOTIFIER_CONTROL, _FORMAT,
1705                                 _LEGACY, value);
1706         } else {
1707             value = FLD_SET_DRF(917E, _SET_NOTIFIER_CONTROL, _FORMAT,
1708                                 _FOUR_WORD, value);
1709         }
1710 
1711         value = FLD_SET_DRF_NUM(917E, _SET_NOTIFIER_CONTROL, _OFFSET,
1712                                 pNIso->offsetInWords, value);
1713 
1714         value = FLD_SET_DRF_NUM(917E, _SET_NOTIFIER_CONTROL, _MODE,
1715                                 pHwState->completionNotifier.awaken ?
1716                                 NV917E_SET_NOTIFIER_CONTROL_MODE_WRITE_AWAKEN :
1717                                 NV917E_SET_NOTIFIER_CONTROL_MODE_WRITE, value);
1718 
1719         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMA_NOTIFIER, 1);
1720         nvDmaSetEvoMethodData(pChannel, pNIso->pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1721 
1722         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_NOTIFIER_CONTROL, 1);
1723         nvDmaSetEvoMethodData(pChannel, value);
1724     }
1725 
1726     /* program semaphore */
1727     nvAssertSameSemaphoreSurface(pHwState);
1728 
1729     if (pHwState->syncObject.u.semaphores.acquireSurface.pSurfaceEvo == NULL) {
1730 
1731         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMA_SEMAPHORE, 1);
1732         nvDmaSetEvoMethodData(pChannel, 0);
1733 
1734         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SEMAPHORE_CONTROL, 1);
1735         nvDmaSetEvoMethodData(pChannel, 0);
1736 
1737     } else {
1738         const NVFlipNIsoSurfaceEvoHwState *pNIso =
1739          &pHwState->syncObject.u.semaphores.acquireSurface;
1740         value = 0;
1741 
1742         if (pNIso->format == NVKMS_NISO_FORMAT_LEGACY) {
1743             value = FLD_SET_DRF(917E, _SET_SEMAPHORE_CONTROL, _FORMAT,
1744                                 _LEGACY, value);
1745         } else {
1746             value = FLD_SET_DRF(917E, _SET_SEMAPHORE_CONTROL, _FORMAT,
1747                                 _FOUR_WORD, value);
1748         }
1749 
1750         value = FLD_SET_DRF_NUM(917E, _SET_SEMAPHORE_CONTROL, _OFFSET,
1751                                 pNIso->offsetInWords, value);
1752 
1753         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMA_SEMAPHORE, 1);
1754         nvDmaSetEvoMethodData(pChannel, pNIso->pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1755 
1756         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SEMAPHORE_ACQUIRE, 1);
1757         nvDmaSetEvoMethodData(pChannel,
1758             pHwState->syncObject.u.semaphores.acquireValue);
1759 
1760         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SEMAPHORE_RELEASE, 1);
1761         nvDmaSetEvoMethodData(pChannel,
1762             pHwState->syncObject.u.semaphores.releaseValue);
1763 
1764         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SEMAPHORE_CONTROL, 1);
1765         nvDmaSetEvoMethodData(pChannel, value);
1766     }
1767 
1768     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_TIMESTAMP_ORIGIN_LO, 2);
1769     nvDmaSetEvoMethodData(pChannel, 0);
1770     nvDmaSetEvoMethodData(pChannel, 0);
1771 
1772     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_UPDATE_TIMESTAMP_LO, 2);
1773     nvDmaSetEvoMethodData(pChannel, NvU64_LO32(pHwState->timeStamp));
1774     nvDmaSetEvoMethodData(pChannel, NvU64_HI32(pHwState->timeStamp));
1775 
1776     if (pHwState->timeStamp == 0) {
1777         value = NV917E_SET_PRESENT_CONTROL_BEGIN_MODE_ASAP;
1778     } else {
1779         value = NV917E_SET_PRESENT_CONTROL_BEGIN_MODE_TIMESTAMP;
1780     }
1781     nvAssert(!pHwState->tearing);
1782     nvAssert(!pHwState->vrrTearing);
1783     nvAssert(!pHwState->perEyeStereoFlip);
1784 
1785     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_PRESENT_CONTROL, 1);
1786     nvDmaSetEvoMethodData(pChannel,
1787         DRF_NUM(917E, _SET_PRESENT_CONTROL, _BEGIN_MODE, value) |
1788         DRF_NUM(917E, _SET_PRESENT_CONTROL, _MIN_PRESENT_INTERVAL,
1789                 pHwState->minPresentInterval));
1790 
1791     if (!pSurfaceEvo) {
1792         // Disable overlay on this head.
1793         nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMAS_ISO(NVKMS_LEFT), 1);
1794         nvDmaSetEvoMethodData(pChannel, 0);
1795         return;
1796     }
1797 
1798     nvAssert(pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1799 
1800     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SIZE_IN, 1);
1801     nvDmaSetEvoMethodData(pChannel,
1802         DRF_NUM(917E, _SET_SIZE_IN, _WIDTH, pHwState->sizeIn.width) |
1803         DRF_NUM(917E, _SET_SIZE_IN, _HEIGHT, pHwState->sizeIn.height));
1804 
1805     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_SIZE_OUT, 1);
1806     nvDmaSetEvoMethodData(pChannel, DRF_NUM(917E, _SET_SIZE_OUT, _WIDTH,
1807                                      pHwState->sizeOut.width));
1808 
1809     // Set the surface parameters.
1810     nvDmaSetStartEvoMethod(pChannel, NV917E_SURFACE_SET_OFFSET(NVKMS_LEFT), 1);
1811     nvDmaSetEvoMethodData(pChannel,
1812         DRF_NUM(917E, _SURFACE_SET_OFFSET, _ORIGIN,
1813                 nvCtxDmaOffsetFromBytes(pSurfaceEvo->planes[0].offset)));
1814 
1815     nvDmaSetStartEvoMethod(pChannel, NV917E_SURFACE_SET_SIZE, 1);
1816     nvDmaSetEvoMethodData(pChannel,
1817         DRF_NUM(917E, _SURFACE_SET_SIZE, _WIDTH, pSurfaceEvo->widthInPixels) |
1818         DRF_NUM(917E, _SURFACE_SET_SIZE, _HEIGHT, pSurfaceEvo->heightInPixels));
1819 
1820     nvDmaSetStartEvoMethod(pChannel, NV917E_SURFACE_SET_STORAGE, 1);
1821     nvDmaSetEvoMethodData(pChannel, EvoComputeSetStorage90(pDevEvo, pSurfaceEvo));
1822 
1823     nvDmaSetStartEvoMethod(pChannel, NV917E_SURFACE_SET_PARAMS, 1);
1824     nvDmaSetEvoMethodData(pChannel,
1825         DRF_NUM(917E, _SURFACE_SET_PARAMS, _FORMAT,
1826         EvoOverlayFormatFromKmsFormat91(pSurfaceEvo->format)) |
1827         DRF_DEF(917E, _SURFACE_SET_PARAMS, _COLOR_SPACE, _RGB));
1828 
1829     SetCscMatrix(pChannel, NV917E_SET_CSC_RED2RED, &pHwState->cscMatrix, 0);
1830 
1831     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_CONTEXT_DMAS_ISO(NVKMS_LEFT), 1);
1832     nvDmaSetEvoMethodData(pChannel, pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle);
1833 
1834     nvAssert(pHwState->inputLut.pLutSurfaceEvo == NULL);
1835 }
1836 
1837 static NvBool
needToReprogramCoreSurface(NVDevEvoPtr pDevEvo,const NvU32 sd,const NvU32 head,const NVSurfaceEvoRec * pNewSurfaceEvo)1838 needToReprogramCoreSurface(NVDevEvoPtr pDevEvo,
1839                            const NvU32 sd,
1840                            const NvU32 head,
1841                            const NVSurfaceEvoRec *pNewSurfaceEvo)
1842 {
1843     const NVDispEvoRec *pDispEvo = pDevEvo->gpus[sd].pDispEvo;
1844     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
1845     NvBool  enableBaseLut = pHeadState->lut.baseLutEnabled;
1846 
1847     const NVSurfaceEvoRec *pCurrCoreSurfaceEvo =
1848         pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head];
1849     const NvBool currIsBaseSurfSpecified =
1850         pDevEvo->pSubDevices[sd]->isBaseSurfSpecified[head];
1851     const NvU32 currHeightInPixels = pCurrCoreSurfaceEvo != NULL ?
1852         pCurrCoreSurfaceEvo->heightInPixels : 0;
1853     const NvU32 currWidthInPixels = pCurrCoreSurfaceEvo != NULL ?
1854         pCurrCoreSurfaceEvo->widthInPixels : 0;
1855     const enum NvKmsSurfaceMemoryFormat currFormat =
1856         pCurrCoreSurfaceEvo != NULL ?
1857         pCurrCoreSurfaceEvo->format : NvKmsSurfaceMemoryFormatI8;
1858 
1859     const NvBool newIsBaseSurfSpecified = pNewSurfaceEvo != NULL;
1860     const NvU32 newHeightInPixels = pNewSurfaceEvo != NULL ?
1861         pNewSurfaceEvo->heightInPixels : 0;
1862     const NvU32 newWidthInPixels = pNewSurfaceEvo != NULL ?
1863         pNewSurfaceEvo->widthInPixels : 0;
1864     const enum NvKmsSurfaceMemoryFormat newFormat = pNewSurfaceEvo != NULL ?
1865         pNewSurfaceEvo->format : NvKmsSurfaceMemoryFormatI8;
1866 
1867     /* If base channel flips from NULL to non-NULL surface or vice-versa */
1868     if (currIsBaseSurfSpecified != newIsBaseSurfSpecified) {
1869         return TRUE;
1870     }
1871 
1872     /*
1873      * Reprogram the core surface if the current and new base surfaces have
1874      * different size or format. The format check is needed to enable/disable
1875      * the input lut if the input lut is not explicitly enabled/disabled by
1876      * client and the base surface if flipping to or flipping away from the I8
1877      * format.
1878      */
1879     if (newIsBaseSurfSpecified) {
1880 
1881         if (newWidthInPixels != currWidthInPixels ||
1882                 newHeightInPixels != currHeightInPixels) {
1883             return TRUE;
1884         }
1885 
1886         if (!enableBaseLut &&
1887             newFormat != currFormat &&
1888             (currFormat == NvKmsSurfaceMemoryFormatI8 ||
1889                 newFormat == NvKmsSurfaceMemoryFormatI8)) {
1890             return TRUE;
1891         }
1892     }
1893 
1894     return !currIsBaseSurfSpecified;
1895 }
1896 
1897 static void
EvoPushUpdateCompositionIfNeeded(NVDevEvoPtr pDevEvo,const NvU32 sd,NVEvoChannelPtr pChannel,const NVFlipChannelEvoHwState * pHwState,NVEvoUpdateState * updateState,NvBool bypassComposition)1898 EvoPushUpdateCompositionIfNeeded(NVDevEvoPtr pDevEvo,
1899                                  const NvU32 sd,
1900                                  NVEvoChannelPtr pChannel,
1901                                  const NVFlipChannelEvoHwState *pHwState,
1902                                  NVEvoUpdateState *updateState,
1903                                  NvBool bypassComposition)
1904 {
1905     const NVSurfaceEvoRec *pNewSurfaceEvo = pHwState->pSurfaceEvo[NVKMS_LEFT];
1906     NvBool updateComposition = FALSE;
1907     const NVFlipChannelEvoHwState *pBaseHwState = NULL;
1908     const NVFlipChannelEvoHwState *pOverlayHwState = NULL;
1909     NvU32 head = NV_INVALID_HEAD;
1910 
1911     if (pNewSurfaceEvo == NULL) {
1912         return;
1913     }
1914 
1915     /*
1916      * Re-program the composition parameters if this is first layer update, or
1917      * if color key selection method is changed, or if layer is using source
1918      * color keying and color key is changed.
1919      */
1920 
1921     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL) != 0) {
1922         head = NV_EVO_CHANNEL_MASK_BASE_HEAD_NUMBER(pChannel->channelMask);
1923         pOverlayHwState =
1924             &pDevEvo->gpus[sd].headState[head].layer[NVKMS_OVERLAY_LAYER];
1925         pBaseHwState = pHwState;
1926 
1927         if ((!pDevEvo->pSubDevices[sd]->baseComp[head].initialized) ||
1928 
1929             (pHwState->composition.colorKeySelect !=
1930                 pDevEvo->pSubDevices[sd]->baseComp[head].colorKeySelect) ||
1931 
1932             ((pHwState->composition.colorKeySelect ==
1933                   NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC) &&
1934              (pNewSurfaceEvo->format !=
1935                   pDevEvo->pSubDevices[sd]->baseSurfFormat[head] ||
1936               nvkms_memcmp(&pHwState->composition.colorKey,
1937                            &pDevEvo->pSubDevices[sd]->baseComp[head].colorKey,
1938                            sizeof(&pHwState->composition.colorKey)) != 0))) {
1939 
1940             pDevEvo->pSubDevices[sd]->baseComp[head].initialized = TRUE;
1941             pDevEvo->pSubDevices[sd]->baseComp[head].colorKeySelect =
1942                 pHwState->composition.colorKeySelect;
1943             pDevEvo->pSubDevices[sd]->baseComp[head].colorKey =
1944                 pHwState->composition.colorKey;
1945             updateComposition = TRUE;
1946         }
1947     }
1948 
1949     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0) {
1950         head = NV_EVO_CHANNEL_MASK_OVERLAY_HEAD_NUMBER(pChannel->channelMask);
1951         pBaseHwState =
1952             &pDevEvo->gpus[sd].headState[head].layer[NVKMS_MAIN_LAYER];
1953         pOverlayHwState = pHwState;
1954 
1955         if ((!pDevEvo->pSubDevices[sd]->overlayComp[head].initialized) ||
1956 
1957             (pHwState->composition.colorKeySelect !=
1958                 pDevEvo->pSubDevices[sd]->overlayComp[head].colorKeySelect) ||
1959 
1960             ((pHwState->composition.colorKeySelect ==
1961                   NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC) &&
1962              (pNewSurfaceEvo->format !=
1963                   pDevEvo->pSubDevices[sd]->overlaySurfFormat[head] ||
1964               nvkms_memcmp(&pHwState->composition.colorKey,
1965                            &pDevEvo->pSubDevices[sd]->overlayComp[head].colorKey,
1966                            sizeof(&pHwState->composition.colorKey)) != 0))) {
1967 
1968             pDevEvo->pSubDevices[sd]->overlayComp[head].initialized = TRUE;
1969             pDevEvo->pSubDevices[sd]->overlayComp[head].colorKeySelect =
1970                 pHwState->composition.colorKeySelect;
1971             pDevEvo->pSubDevices[sd]->overlayComp[head].colorKey =
1972                 pHwState->composition.colorKey;
1973             updateComposition = TRUE;
1974         }
1975     }
1976 
1977     if (updateComposition) {
1978         nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
1979         EvoPushUpdateComposition(pDevEvo, head, pBaseHwState, pOverlayHwState,
1980                                  updateState, bypassComposition);
1981         nvPopEvoSubDevMask(pDevEvo);
1982     }
1983 }
1984 
EvoFlip90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,const NVFlipChannelEvoHwState * pHwState,NVEvoUpdateState * updateState,NvBool bypassComposition)1985 static void EvoFlip90(NVDevEvoPtr pDevEvo,
1986                       NVEvoChannelPtr pChannel,
1987                       const NVFlipChannelEvoHwState *pHwState,
1988                       NVEvoUpdateState *updateState,
1989                       NvBool bypassComposition)
1990 {
1991     NvU32 sd;
1992 
1993     FOR_EACH_SUBDEV_IN_MASK(sd, nvPeekEvoSubDevMask(pDevEvo)) {
1994         EvoPushUpdateCompositionIfNeeded(pDevEvo, sd, pChannel, pHwState,
1995                                          updateState, bypassComposition);
1996     } FOR_EACH_SUBDEV_IN_MASK_END
1997 
1998     if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL) != 0) {
1999         const NvU32 head =
2000             NV_EVO_CHANNEL_MASK_BASE_HEAD_NUMBER(pChannel->channelMask);
2001 
2002         FOR_EACH_SUBDEV_IN_MASK(sd, nvPeekEvoSubDevMask(pDevEvo)) {
2003             if (needToReprogramCoreSurface(
2004                     pDevEvo,
2005                     sd,
2006                     head,
2007                     pHwState->pSurfaceEvo[NVKMS_LEFT])) {
2008                 const struct NvKmsCscMatrix zeroCscMatrix = { };
2009 
2010                 nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
2011                 EvoPushSetCoreSurfaceMethodsForOneSd(pDevEvo, sd, head,
2012                     pHwState->pSurfaceEvo[NVKMS_LEFT],
2013                     &zeroCscMatrix, updateState);
2014                 nvPopEvoSubDevMask(pDevEvo);
2015             }
2016 
2017             if (pHwState->pSurfaceEvo[NVKMS_LEFT] != NULL) {
2018                 pDevEvo->pSubDevices[sd]->isBaseSurfSpecified[head] = TRUE;
2019                 pDevEvo->pSubDevices[sd]->baseSurfFormat[head] =
2020                     pHwState->pSurfaceEvo[NVKMS_LEFT]->format;
2021             } else {
2022                 pDevEvo->pSubDevices[sd]->isBaseSurfSpecified[head] = FALSE;
2023             }
2024         } FOR_EACH_SUBDEV_IN_MASK_END
2025 
2026         FlipBase90(pDevEvo, pChannel, pHwState, updateState);
2027 
2028         if (pHwState->vrrTearing) {
2029             int head = NV_EVO_CHANNEL_MASK_BASE_HEAD_NUMBER(pChannel->channelMask);
2030             NvU32 sd, subDeviceMask = nvPeekEvoSubDevMask(pDevEvo);
2031 
2032             for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
2033                 if (subDeviceMask & (1 << sd)) {
2034                     updateState->subdev[sd].base[head].vrrTearing = TRUE;
2035                 }
2036             }
2037         }
2038     } else if ((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0) {
2039         NvBool interlockWithCore = FALSE;
2040 
2041         FlipOverlay90(pDevEvo, pChannel, pHwState, &interlockWithCore);
2042 
2043         if (interlockWithCore) {
2044             nvUpdateUpdateState(pDevEvo, updateState, pDevEvo->core);
2045         }
2046     } else {
2047         nvAssert(!"Unknown channel mask in EvoFlip90");
2048     }
2049 
2050     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2051 }
2052 
EvoFlipTransitionWAR90(NVDevEvoPtr pDevEvo,NvU32 sd,NvU32 head,const NVEvoSubDevHeadStateRec * pSdHeadState,const NVFlipEvoHwState * pFlipState,NVEvoUpdateState * updateState)2053 static void EvoFlipTransitionWAR90(NVDevEvoPtr pDevEvo, NvU32 sd, NvU32 head,
2054                                    const NVEvoSubDevHeadStateRec *pSdHeadState,
2055                                    const NVFlipEvoHwState *pFlipState,
2056                                    NVEvoUpdateState *updateState)
2057 {
2058     /* Nothing to do pre-Turing */
2059 }
2060 
2061 /*!
2062  * Pack the given abstract color key into a key and mask as required
2063  * by the display engine.
2064  *
2065  * \param[in]   format  NVKMS format for the input surface
2066  * \param[in]   key     NVKMS representation of a color key
2067  * \param[out]  pValue  NV857E_SET_KEY_COLOR_COLOR value
2068  * \param[out]  pMask   NV857E_SET_KEY_COLOR_MASK value
2069  */
EvoPackColorKey91(enum NvKmsSurfaceMemoryFormat format,const NVColorKey key,NvU32 * pValue,NvU32 * pMask)2070 static void EvoPackColorKey91(enum NvKmsSurfaceMemoryFormat format,
2071                               const NVColorKey key,
2072                               NvU32 *pValue, NvU32 *pMask)
2073 {
2074     NvU32 value = 0, mask = 0;
2075     switch (format) {
2076     case NvKmsSurfaceMemoryFormatR5G6B5:
2077         if (key.matchR) {
2078             mask  |=          0x1f  << 11;
2079             value |= (key.r & 0x1f) << 11;
2080         }
2081         if (key.matchG) {
2082             mask  |=          0x3f  << 5;
2083             value |= (key.g & 0x3f) << 5;
2084         }
2085         if (key.matchB) {
2086             mask  |=          0x1f  << 0;
2087             value |= (key.b & 0x1f) << 0;
2088         }
2089         break;
2090     case NvKmsSurfaceMemoryFormatA1R5G5B5:
2091     case NvKmsSurfaceMemoryFormatX1R5G5B5:
2092         if (key.matchA) {
2093             mask  |=          0x1  << 15;
2094             value |= (key.a & 0x1) << 15;
2095         }
2096         if (key.matchR) {
2097             mask  |=          0x1f  << 10;
2098             value |= (key.r & 0x1f) << 10;
2099         }
2100         if (key.matchG) {
2101             mask  |=          0x1f  << 5;
2102             value |= (key.g & 0x1f) << 5;
2103         }
2104         if (key.matchB) {
2105             mask  |=          0x1f  << 0;
2106             value |= (key.b & 0x1f) << 0;
2107         }
2108         break;
2109     case NvKmsSurfaceMemoryFormatA8R8G8B8:
2110     case NvKmsSurfaceMemoryFormatX8R8G8B8:
2111         if (key.matchA) {
2112             /* Only one bit of alpha is handled by the hw. */
2113             mask  |=          0x1  << 31;
2114             value |= (key.a ? 1:0) << 31;
2115         }
2116         if (key.matchR) {
2117             mask  |=          0xff  << 16;
2118             value |= (key.r & 0xff) << 16;
2119         }
2120         if (key.matchG) {
2121             mask  |=          0xff  << 8;
2122             value |= (key.g & 0xff) << 8;
2123         }
2124         if (key.matchB) {
2125             mask  |=          0xff  << 0;
2126             value |= (key.b & 0xff) << 0;
2127         }
2128         break;
2129     case NvKmsSurfaceMemoryFormatA8B8G8R8:
2130     case NvKmsSurfaceMemoryFormatX8B8G8R8:
2131         if (key.matchA) {
2132             /* Only one bit of alpha is handled by the hw. */
2133             mask  |=          0x1  << 31;
2134             value |= (key.a ? 1:0) << 31;
2135         }
2136         if (key.matchB) {
2137             mask  |=          0xff  << 16;
2138             value |= (key.b & 0xff) << 16;
2139         }
2140         if (key.matchG) {
2141             mask  |=          0xff  << 8;
2142             value |= (key.g & 0xff) << 8;
2143         }
2144         if (key.matchR) {
2145             mask  |=          0xff  << 0;
2146             value |= (key.r & 0xff) << 0;
2147         }
2148         break;
2149     case NvKmsSurfaceMemoryFormatA2B10G10R10:
2150     case NvKmsSurfaceMemoryFormatX2B10G10R10:
2151         if (key.matchA) {
2152             /* Only one bit of alpha is handled by the hw. */
2153             mask  |=          0x1  << 31;
2154             value |= (key.a ? 1:0) << 31;
2155         }
2156         if (key.matchB) {
2157             mask  |=          0x3ff  << 20;
2158             value |= (key.b & 0x3ff) << 20;
2159         }
2160         if (key.matchG) {
2161             mask  |=          0x3ff  << 10;
2162             value |= (key.g & 0x3ff) << 10;
2163         }
2164         if (key.matchR) {
2165             mask  |=          0x3ff  << 0;
2166             value |= (key.r & 0x3ff) << 0;
2167         }
2168         break;
2169     case NvKmsSurfaceMemoryFormatI8:
2170     case NvKmsSurfaceMemoryFormatRF16GF16BF16AF16:
2171     case NvKmsSurfaceMemoryFormatRF16GF16BF16XF16:
2172     case NvKmsSurfaceMemoryFormatR16G16B16A16:
2173     case NvKmsSurfaceMemoryFormatRF32GF32BF32AF32:
2174     case NvKmsSurfaceMemoryFormatY8_U8__Y8_V8_N422:
2175     case NvKmsSurfaceMemoryFormatU8_Y8__V8_Y8_N422:
2176     case NvKmsSurfaceMemoryFormatY8___U8V8_N444:
2177     case NvKmsSurfaceMemoryFormatY8___V8U8_N444:
2178     case NvKmsSurfaceMemoryFormatY8___U8V8_N422:
2179     case NvKmsSurfaceMemoryFormatY8___V8U8_N422:
2180     case NvKmsSurfaceMemoryFormatY8___U8V8_N420:
2181     case NvKmsSurfaceMemoryFormatY8___V8U8_N420:
2182     case NvKmsSurfaceMemoryFormatY10___U10V10_N444:
2183     case NvKmsSurfaceMemoryFormatY10___V10U10_N444:
2184     case NvKmsSurfaceMemoryFormatY10___U10V10_N422:
2185     case NvKmsSurfaceMemoryFormatY10___V10U10_N422:
2186     case NvKmsSurfaceMemoryFormatY10___U10V10_N420:
2187     case NvKmsSurfaceMemoryFormatY10___V10U10_N420:
2188     case NvKmsSurfaceMemoryFormatY12___U12V12_N444:
2189     case NvKmsSurfaceMemoryFormatY12___V12U12_N444:
2190     case NvKmsSurfaceMemoryFormatY12___U12V12_N422:
2191     case NvKmsSurfaceMemoryFormatY12___V12U12_N422:
2192     case NvKmsSurfaceMemoryFormatY12___U12V12_N420:
2193     case NvKmsSurfaceMemoryFormatY12___V12U12_N420:
2194     case NvKmsSurfaceMemoryFormatY8___U8___V8_N444:
2195     case NvKmsSurfaceMemoryFormatY8___U8___V8_N420:
2196         nvAssert(!"Unhandled format in nvEvo1PackColorKey");
2197         break;
2198     }
2199 
2200     *pMask = mask;
2201     *pValue = value;
2202 }
2203 
EvoOverlayCompositionControlFromNvKmsCompositionParams(const NVFlipChannelEvoHwState * pBaseHwState,const NVFlipChannelEvoHwState * pOverlayHwState,NvU32 * pMode,NvU32 * pColorKeyValue,NvU32 * pColorKeyMask)2204 static NvBool EvoOverlayCompositionControlFromNvKmsCompositionParams(
2205     const NVFlipChannelEvoHwState *pBaseHwState,
2206     const NVFlipChannelEvoHwState *pOverlayHwState,
2207     NvU32 *pMode,
2208     NvU32 *pColorKeyValue,
2209     NvU32 *pColorKeyMask)
2210 {
2211     const struct NvKmsCompositionParams *pBaseCompParams =
2212         &pBaseHwState->composition;
2213     const struct NvKmsCompositionParams *pOverlayCompParams =
2214         &pOverlayHwState->composition;
2215 
2216     switch (pOverlayCompParams->colorKeySelect) {
2217     case NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE:
2218         if (pOverlayCompParams->blendingMode[1] == NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE) {
2219             *pMode = NV917E_SET_COMPOSITION_CONTROL_MODE_OPAQUE;
2220             *pColorKeyValue = *pColorKeyMask = 0;
2221         } else {
2222             return FALSE;
2223         }
2224         break;
2225     case NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC:
2226         if ((pOverlayCompParams->blendingMode[0] ==
2227                 NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE) &&
2228             (pOverlayCompParams->blendingMode[1] ==
2229                 NVKMS_COMPOSITION_BLENDING_MODE_TRANSPARENT)) {
2230 
2231             *pMode = NV917E_SET_COMPOSITION_CONTROL_MODE_SOURCE_COLOR_VALUE_KEYING;
2232 
2233             if (pOverlayHwState->pSurfaceEvo[NVKMS_LEFT] != NULL) {
2234                 EvoPackColorKey91(pOverlayHwState->pSurfaceEvo[NVKMS_LEFT]->format,
2235                                   pOverlayCompParams->colorKey,
2236                                   pColorKeyValue,
2237                                   pColorKeyMask);
2238             } else {
2239                 *pColorKeyValue = *pColorKeyMask = 0;
2240             }
2241 
2242         } else {
2243             return FALSE;
2244         }
2245         break;
2246     case NVKMS_COMPOSITION_COLOR_KEY_SELECT_DST:
2247         if ((pBaseCompParams->colorKeySelect ==
2248                 NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE) &&
2249             (pOverlayCompParams->blendingMode[1] ==
2250                 NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE)) {
2251             *pMode = NV917E_SET_COMPOSITION_CONTROL_MODE_OPAQUE;
2252             *pColorKeyValue = *pColorKeyMask = 0;
2253         } else if ((pBaseCompParams->colorKeySelect ==
2254                         NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC) &&
2255                    (pOverlayCompParams->blendingMode[1] ==
2256                         NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE) &&
2257                    (pOverlayCompParams->blendingMode[0] ==
2258                         NVKMS_COMPOSITION_BLENDING_MODE_TRANSPARENT)) {
2259 
2260             *pMode = NV917E_SET_COMPOSITION_CONTROL_MODE_DESTINATION_COLOR_VALUE_KEYING;
2261 
2262             if (pBaseHwState->pSurfaceEvo[NVKMS_LEFT] != NULL) {
2263                 EvoPackColorKey91(pBaseHwState->pSurfaceEvo[NVKMS_LEFT]->format,
2264                                   pBaseCompParams->colorKey,
2265                                   pColorKeyValue,
2266                                   pColorKeyMask);
2267             } else {
2268                 *pColorKeyValue = *pColorKeyMask = 0;
2269             }
2270 
2271         } else {
2272             return FALSE;
2273         }
2274         break;
2275     default:
2276         return FALSE;
2277     }
2278 
2279     return TRUE;
2280 }
2281 
2282 static void
EvoPushUpdateComposition(NVDevEvoPtr pDevEvo,const int head,const NVFlipChannelEvoHwState * pBaseHwState,const NVFlipChannelEvoHwState * pOverlayHwState,NVEvoUpdateState * updateState,NvBool bypassComposition)2283 EvoPushUpdateComposition(NVDevEvoPtr pDevEvo,
2284                          const int head,
2285                          const NVFlipChannelEvoHwState *pBaseHwState,
2286                          const NVFlipChannelEvoHwState *pOverlayHwState,
2287                          NVEvoUpdateState *updateState,
2288                          NvBool bypassComposition)
2289 {
2290 
2291     /* Composition is always programmed through the overlay channel. */
2292     NVEvoChannelPtr pChannel = pDevEvo->overlay[head];
2293     NvU32 colorKeyValue = 0, colorKeyMask = 0;
2294     NvU32 compositionModeValue = 0;
2295 
2296     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2297 
2298     if (!EvoOverlayCompositionControlFromNvKmsCompositionParams(
2299             pBaseHwState, pOverlayHwState,
2300             &compositionModeValue,
2301             &colorKeyValue,
2302             &colorKeyMask)) {
2303         /*
2304          * composition mode is validated during
2305          * nvUpdateFlipEvoHwState(), so it should always be valid when
2306          * we get here.
2307         */
2308         nvAssert(!"Invalid composition params");
2309         return;
2310     }
2311 
2312     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_COMPOSITION_CONTROL, 1);
2313     nvDmaSetEvoMethodData(pChannel, compositionModeValue);
2314 
2315     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_KEY_COLOR_LO, 2);
2316     nvDmaSetEvoMethodData(pChannel, colorKeyValue);
2317     nvDmaSetEvoMethodData(pChannel, 0);
2318 
2319     nvDmaSetStartEvoMethod(pChannel, NV917E_SET_KEY_MASK_LO, 2);
2320     nvDmaSetEvoMethodData(pChannel, colorKeyMask);
2321     nvDmaSetEvoMethodData(pChannel, 0);
2322 }
2323 
2324 /*
2325  * The LUT entries in INDEX_1025_UNITY_RANGE have 16 bits, with the
2326  * black value at 24576, and the white at 49151. Since the effective
2327  * range is 16384, we treat this as a 14-bit LUT.  However, we need to
2328  * clear the low 3 bits to WAR hardware bug 813188.  This gives us
2329  * 14-bit LUT values, but only 11 bits of precision.
2330  */
ColorToLUTEntry(NvU16 val)2331 static inline NvU16 ColorToLUTEntry(NvU16 val)
2332 {
2333     const NvU16 val14bit = val >> 2;
2334     return (val14bit & ~7) + 24576;
2335 }
2336 
2337 /* In INDEX_1025_UNITY_RANGE, the LUT indices for color depths with less
2338  * than 10 bpc are the indices you'd have in 257-entry mode multiplied
2339  * by four. So, you under-replicate all but the two least significant bits.
2340  * Since when is EVO supposed to make sense?
2341  */
2342 static void
EvoFillLUTSurface90(NVEvoLutEntryRec * pLUTBuffer,const NvU16 * red,const NvU16 * green,const NvU16 * blue,int nColorMapEntries,int depth)2343 EvoFillLUTSurface90(NVEvoLutEntryRec *pLUTBuffer,
2344                     const NvU16 *red,
2345                     const NvU16 *green,
2346                     const NvU16 *blue,
2347                     int nColorMapEntries, int depth)
2348 {
2349     int i, lutIndex;
2350 
2351     switch (depth) {
2352     case 15:
2353         for (i = 0; i < nColorMapEntries; i++) {
2354             lutIndex = PALETTE_DEPTH_SHIFT(i, 5) << 2;
2355             pLUTBuffer[lutIndex].Red   = ColorToLUTEntry(red[i]);
2356             pLUTBuffer[lutIndex].Green = ColorToLUTEntry(green[i]);
2357             pLUTBuffer[lutIndex].Blue  = ColorToLUTEntry(blue[i]);
2358         }
2359         break;
2360     case 16:
2361         for (i = 0; i < nColorMapEntries; i++) {
2362             pLUTBuffer[PALETTE_DEPTH_SHIFT(i, 6) << 2].Green = ColorToLUTEntry(green[i]);
2363             if (i < 32) {
2364                 lutIndex = PALETTE_DEPTH_SHIFT(i, 5) << 2;
2365                 pLUTBuffer[lutIndex].Red  = ColorToLUTEntry(red[i]);
2366                 pLUTBuffer[lutIndex].Blue = ColorToLUTEntry(blue[i]);
2367             }
2368         }
2369         break;
2370     case 8:
2371     case 24:
2372         for (i = 0; i < nColorMapEntries; i++) {
2373             lutIndex = i << 2;
2374             pLUTBuffer[lutIndex].Red   = ColorToLUTEntry(red[i]);
2375             pLUTBuffer[lutIndex].Green = ColorToLUTEntry(green[i]);
2376             pLUTBuffer[lutIndex].Blue  = ColorToLUTEntry(blue[i]);
2377         }
2378         break;
2379     case 30:
2380         for (i = 0; i < nColorMapEntries; i++) {
2381             pLUTBuffer[i].Red   = ColorToLUTEntry(red[i]);
2382             pLUTBuffer[i].Green = ColorToLUTEntry(green[i]);
2383             pLUTBuffer[i].Blue  = ColorToLUTEntry(blue[i]);
2384         }
2385         break;
2386     default:
2387         nvAssert(!"invalid depth");
2388         return;
2389     }
2390 }
2391 
2392 static void
EvoPushSetLUTContextDmaMethodsForOneSd(NVDevEvoRec * pDevEvo,const NvU32 sd,const NvU32 head,const NvU32 ctxdma,NvBool enableBaseLut,const NvBool enableOutputLut,NVEvoUpdateState * updateState)2393 EvoPushSetLUTContextDmaMethodsForOneSd(NVDevEvoRec *pDevEvo,
2394                                        const NvU32 sd,
2395                                        const NvU32 head,
2396                                        const NvU32 ctxdma,
2397                                        NvBool enableBaseLut,
2398                                        const NvBool enableOutputLut,
2399                                        NVEvoUpdateState *updateState)
2400 {
2401     NVEvoChannelPtr pChannel = pDevEvo->core;
2402     NvU64 offset;
2403     const NVSurfaceEvoRec *pCoreSurfaceEvo =
2404         pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head];
2405     const NvBool surfaceDepth8 = (pCoreSurfaceEvo != NULL) ?
2406         (pCoreSurfaceEvo->format == NvKmsSurfaceMemoryFormatI8) : FALSE;
2407 
2408     nvAssert(nvPeekEvoSubDevMask(pDevEvo) == NVBIT(sd));
2409 
2410     // Depth 8 requires the base LUT to be enabled.
2411     if (ctxdma && !enableBaseLut && surfaceDepth8) {
2412         // TODO: Is this still required?  Callers should specify the LUT at
2413         // modeset time now.
2414         enableBaseLut = TRUE;
2415     }
2416 
2417     nvAssert(ctxdma || (!enableBaseLut && !enableOutputLut));
2418 
2419     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2420 
2421     /* Program the base LUT */
2422 
2423     offset = offsetof(NVEvoLutDataRec, base);
2424     nvAssert((offset & 0xff) == 0);
2425 
2426     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_BASE_LUT_LO(head), 1);
2427     nvDmaSetEvoMethodData(pChannel,
2428         DRF_DEF(917D, _HEAD_SET_BASE_LUT_LO, _MODE, _INDEX_1025_UNITY_RANGE) |
2429         (enableBaseLut ? DRF_DEF(917D, _HEAD_SET_BASE_LUT_LO, _ENABLE, _ENABLE) :
2430                          DRF_DEF(917D, _HEAD_SET_BASE_LUT_LO, _ENABLE, _DISABLE)) |
2431         DRF_DEF(917D, _HEAD_SET_BASE_LUT_LO, _NEVER_YIELD_TO_BASE, _DISABLE));
2432 
2433     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_BASE_LUT_HI(head), 1);
2434     nvDmaSetEvoMethodData(pChannel,
2435             DRF_NUM(917D, _HEAD_SET_BASE_LUT_HI, _ORIGIN, offset >> 8));
2436 
2437     /* Program the output LUT */
2438 
2439     offset = offsetof(NVEvoLutDataRec, output);
2440     nvAssert((offset & 0xff) == 0);
2441 
2442     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_OUTPUT_LUT_LO(head), 1);
2443     nvDmaSetEvoMethodData(pChannel,
2444         (enableOutputLut ? DRF_DEF(917D, _HEAD_SET_OUTPUT_LUT_LO, _ENABLE, _ENABLE) :
2445                            DRF_DEF(917D, _HEAD_SET_OUTPUT_LUT_LO, _ENABLE, _DISABLE)) |
2446         DRF_DEF(917D, _HEAD_SET_OUTPUT_LUT_LO, _MODE, _INTERPOLATE_1025_UNITY_RANGE) |
2447         DRF_DEF(917D, _HEAD_SET_OUTPUT_LUT_LO, _NEVER_YIELD_TO_BASE, _DISABLE));
2448 
2449     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_OUTPUT_LUT_HI(head), 1);
2450     nvDmaSetEvoMethodData(pChannel,
2451         DRF_NUM(917D, _HEAD_SET_OUTPUT_LUT_HI, _ORIGIN, offset >> 8));
2452 
2453     /* Set the ctxdma that's used by both LUTs */
2454 
2455     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTEXT_DMA_LUT(head), 1);
2456     nvDmaSetEvoMethodData(pChannel,
2457             DRF_NUM(917D, _HEAD_SET_CONTEXT_DMA_LUT, _HANDLE, ctxdma));
2458 
2459     /*
2460      * Use this backdoor to disable "wide pipe" underreplication during
2461      * expansion of color components into the display pipe.  Underreplication
2462      * of a non-zero 8-bit color to more than 8 bits causes lookups to fall
2463      * between LUT entries in a 256-entry LUT, which we don't want.  See bug
2464      * 734919 for details.
2465      * The "wide pipe" may also cause scanout of 8-bit data to an 8-bit OR to
2466      * not be a straight passthrough (bug 895401).
2467      */
2468     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CRC_CONTROL(head), 1);
2469     nvDmaSetEvoMethodData(pChannel,
2470             DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _PRIMARY_OUTPUT, _NONE) |
2471             DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _SECONDARY_OUTPUT, _NONE) |
2472             DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _WIDE_PIPE_CRC, _DISABLE));
2473 }
2474 
EvoSetLUTContextDma90(const NVDispEvoRec * pDispEvo,const int head,NVLutSurfaceEvoPtr pLutSurfEvo,NvBool enableBaseLut,NvBool enableOutputLut,NVEvoUpdateState * updateState,NvBool bypassComposition)2475 static void EvoSetLUTContextDma90(const NVDispEvoRec *pDispEvo,
2476                                   const int head,
2477                                   NVLutSurfaceEvoPtr pLutSurfEvo,
2478                                   NvBool enableBaseLut,
2479                                   NvBool enableOutputLut,
2480                                   NVEvoUpdateState *updateState,
2481                                   NvBool bypassComposition)
2482 {
2483     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
2484     const NvU32 sd = pDispEvo->displayOwner;
2485 
2486     const NvBool coreChannelCtxDmaNonNull =
2487         pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head] != NULL;
2488     const NvU32 ctxdma = (pLutSurfEvo != NULL) ? pLutSurfEvo->surfaceDesc.ctxDmaHandle : 0;
2489 
2490     /*
2491      * If the core channel doesn't have a scanout surface set, then setting the
2492      * LUT context DMA will cause an exception.
2493      */
2494     if (!coreChannelCtxDmaNonNull && ctxdma) {
2495         return;
2496     }
2497 
2498     nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
2499     EvoPushSetLUTContextDmaMethodsForOneSd(
2500         pDevEvo, sd, head, ctxdma, enableBaseLut, enableOutputLut,
2501         updateState);
2502     nvPopEvoSubDevMask(pDevEvo);
2503 }
2504 
2505 #define NV_EVO2_CAP_GET_PIN(cl, n, pEvoCaps, word, name, idx, pCaps) \
2506     (pEvoCaps)->pin[(idx)].flipLock = \
2507         FLD_TEST_DRF(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_##word, \
2508                      _LOCK_PIN##name##USAGE, _FLIP_LOCK, \
2509                      (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_##word]); \
2510     (pEvoCaps)->pin[(idx)].stereo = \
2511         FLD_TEST_DRF(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_##word, \
2512                      _LOCK_PIN##name##USAGE, _STEREO, \
2513                      (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_##word]); \
2514     (pEvoCaps)->pin[(idx)].scanLock = \
2515         FLD_TEST_DRF(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_##word, \
2516                      _LOCK_PIN##name##USAGE, _SCAN_LOCK, \
2517                      (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_##word]);
2518 
2519 /* Take the max of MAX_PIXELS_t_TAP422 and MAX_PIXELS_t_TAP444 */
2520 #define NV_EVO2_CAP_GET_HEAD_MAX_PIXELS(cl, n, pEvoCaps, i, x, t, pCaps) \
2521     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_##t##TAPS].maxPixelsVTaps = \
2522         NV_MAX(REF_VAL(NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_HEAD##i##_##x##_MAX_PIXELS##t##TAP422, \
2523                (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_HEAD##i##_##x]), \
2524                REF_VAL(NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_HEAD##i##_##x##_MAX_PIXELS##t##TAP444, \
2525                (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_HEAD##i##_##x]))
2526 
2527 #define NV_EVO2_CAP_GET_HEAD(cl, n, pEvoCaps, i, x, y, z, a, pCaps) \
2528     (pEvoCaps)->head[(i)].usable = TRUE; \
2529     (pEvoCaps)->head[(i)].maxPClkKHz = \
2530         DRF_VAL(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_CAP_HEAD##i##_##a, _PCLK_MAX, \
2531                 (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_HEAD##i##_##a]) * 10000; \
2532     (pEvoCaps)->head[(i)].scalerCaps.present = TRUE; \
2533     NV_EVO2_CAP_GET_HEAD_MAX_PIXELS(cl, n, pEvoCaps, i, x, 5, pCaps); \
2534     NV_EVO2_CAP_GET_HEAD_MAX_PIXELS(cl, n, pEvoCaps, i, y, 3, pCaps); \
2535     NV_EVO2_CAP_GET_HEAD_MAX_PIXELS(cl, n, pEvoCaps, i, z, 2, pCaps); \
2536     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_8TAPS].maxHDownscaleFactor = NV_U16_MAX; \
2537     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_5TAPS].maxVDownscaleFactor = NV_U16_MAX; \
2538     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_3TAPS].maxVDownscaleFactor = NV_U16_MAX; \
2539     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_2TAPS].maxVDownscaleFactor = NV_U16_MAX; \
2540     (pEvoCaps)->head[(i)].scalerCaps.taps[NV_EVO_SCALER_2TAPS].maxHDownscaleFactor = NV_U16_MAX;
2541 
2542 #define NV_EVO2_CAP_GET_SOR(cl, n, pEvoCaps, i, x, y, pCaps) \
2543     (pEvoCaps)->sor[(i)].dualTMDS = \
2544         FLD_TEST_DRF(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_CAP_SOR##i##_##x, \
2545                      _DUAL_TMDS, _TRUE, \
2546                      (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_SOR##i##_##x]); \
2547     (pEvoCaps)->sor[(i)].maxTMDSClkKHz = \
2548         DRF_VAL(cl##_CORE_NOTIFIER_##n, _CAPABILITIES_CAP_SOR##i##_##y, _TMDS_LVDS_CLK_MAX, \
2549                 (pCaps)[NV##cl##_CORE_NOTIFIER_##n##_CAPABILITIES_CAP_SOR##i##_##y]) * 10000;
2550 
EvoParseCapabilityNotifier3(NVEvoCapabilitiesPtr pEvoCaps,volatile const NvU32 * pCaps)2551 static void EvoParseCapabilityNotifier3(NVEvoCapabilitiesPtr pEvoCaps,
2552                                         volatile const NvU32 *pCaps)
2553 {
2554     // Lock pins
2555     // These magic numbers (5, 6, _A, etc.) are token-pasted into the
2556     // NV917D_CORE_NOTIFIER_3_* macros and can't be autogenerated by the
2557     // preprocessor.  Architecture appears to have no plans to ever fix this.
2558     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  0, 0x0, pCaps);
2559     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  1, 0x1, pCaps);
2560     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  2, 0x2, pCaps);
2561     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  3, 0x3, pCaps);
2562     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  4, 0x4, pCaps);
2563     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  5, 0x5, pCaps);
2564     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  6, 0x6, pCaps);
2565     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 5,  7, 0x7, pCaps);
2566     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6,  8, 0x8, pCaps);
2567     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6,  9, 0x9, pCaps);
2568     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _A, 0xa, pCaps);
2569     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _B, 0xb, pCaps);
2570     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _C, 0xc, pCaps);
2571     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _D, 0xd, pCaps);
2572     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _E, 0xe, pCaps);
2573     NV_EVO2_CAP_GET_PIN(917D, 3, pEvoCaps, 6, _F, 0xf, pCaps);
2574 
2575     // Miscellaneous capabilities
2576     pEvoCaps->misc.supportsInterlaced = TRUE;
2577     pEvoCaps->misc.supportsSemiPlanar = FALSE;
2578     pEvoCaps->misc.supportsPlanar = FALSE;
2579     pEvoCaps->misc.supportsDSI = FALSE;
2580 
2581     // Heads
2582     NV_EVO2_CAP_GET_HEAD(917D, 3, pEvoCaps, 0, 53, 54, 55, 56, pCaps);
2583     NV_EVO2_CAP_GET_HEAD(917D, 3, pEvoCaps, 1, 61, 62, 63, 64, pCaps);
2584     NV_EVO2_CAP_GET_HEAD(917D, 3, pEvoCaps, 2, 69, 70, 71, 72, pCaps);
2585     NV_EVO2_CAP_GET_HEAD(917D, 3, pEvoCaps, 3, 77, 78, 79, 80, pCaps);
2586 
2587     // SORs
2588     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 0, 20, 21, pCaps);
2589     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 1, 22, 23, pCaps);
2590     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 2, 24, 25, pCaps);
2591     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 3, 26, 27, pCaps);
2592     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 4, 28, 29, pCaps);
2593     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 5, 30, 31, pCaps);
2594     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 6, 32, 33, pCaps);
2595     NV_EVO2_CAP_GET_SOR(917D, 3, pEvoCaps, 7, 34, 35, pCaps);
2596 
2597     // Don't need any PIOR caps currently.
2598 }
2599 
EvoGetCapabilities90(NVDevEvoPtr pDevEvo)2600 static NvBool EvoGetCapabilities90(NVDevEvoPtr pDevEvo)
2601 {
2602     NVEvoChannelPtr pChannel = pDevEvo->core;
2603     NVDispEvoPtr pDispEvo;
2604     unsigned int i, sd;
2605     struct NvKmsRRParams rrParams = { NVKMS_ROTATION_0, FALSE, FALSE };
2606     NvU8 layer;
2607 
2608     nvAssert(nvPeekEvoSubDevMask(pDevEvo) == SUBDEVICE_MASK_ALL);
2609 
2610     /* Main layer position and size updates are not supported on EVO. */
2611     for (layer = 0;
2612          layer < ARRAY_LEN(pDevEvo->caps.layerCaps);
2613          layer++) {
2614         if (layer != NVKMS_MAIN_LAYER) {
2615             pDevEvo->caps.layerCaps[layer].supportsWindowMode = TRUE;
2616             pDevEvo->caps.legacyNotifierFormatSizeBytes[layer] =
2617                 NV_DISP_NOTIFICATION_2_SIZEOF;
2618         } else {
2619             pDevEvo->caps.layerCaps[layer].supportsWindowMode = FALSE;
2620             pDevEvo->caps.legacyNotifierFormatSizeBytes[layer] =
2621                NV_DISP_BASE_NOTIFIER_1_SIZEOF;
2622         }
2623     }
2624 
2625     pDevEvo->caps.cursorCompositionCaps =
2626         (struct NvKmsCompositionCapabilities) {
2627             .supportedColorKeySelects =
2628                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE),
2629 
2630             .colorKeySelect = {
2631                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE] = {
2632                     .supportedBlendModes = {
2633                         [1] = NV_EVO2_SUPPORTED_CURSOR_COMP_BLEND_MODES,
2634                     },
2635                 },
2636             }
2637         };
2638 
2639     /* Base doesn't support any composition with underlying layers. */
2640     pDevEvo->caps.layerCaps[NVKMS_MAIN_LAYER].composition =
2641         (struct NvKmsCompositionCapabilities) {
2642             .supportedColorKeySelects =
2643                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE) |
2644                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC),
2645 
2646             .colorKeySelect = {
2647                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE] = {
2648                     .supportedBlendModes = {
2649                         [1] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2650                     },
2651                 },
2652 
2653                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC] = {
2654                     .supportedBlendModes = {
2655                         [0] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2656                         [1] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2657                     },
2658                 },
2659             },
2660         };
2661 
2662     pDevEvo->caps.layerCaps[NVKMS_OVERLAY_LAYER].composition =
2663         (struct NvKmsCompositionCapabilities) {
2664             .supportedColorKeySelects =
2665                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE) |
2666                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC) |
2667                 NVBIT(NVKMS_COMPOSITION_COLOR_KEY_SELECT_DST),
2668 
2669             .colorKeySelect = {
2670                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE] = {
2671                     .supportedBlendModes = {
2672                         [1] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2673                     },
2674                 },
2675 
2676                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_SRC] = {
2677                     .supportedBlendModes = {
2678                         [0] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2679                         [1] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_TRANSPARENT),
2680                     },
2681                 },
2682 
2683                 [NVKMS_COMPOSITION_COLOR_KEY_SELECT_DST] = {
2684                     .supportedBlendModes = {
2685                         [0] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_TRANSPARENT),
2686                         [1] = NVBIT(NVKMS_COMPOSITION_BLENDING_MODE_OPAQUE),
2687                     },
2688                 },
2689             },
2690         };
2691 
2692     pDevEvo->caps.validLayerRRTransforms |=
2693         NVBIT(NvKmsRRParamsToCapBit(&rrParams));
2694 
2695     for (i = NvKmsSurfaceMemoryFormatMin;
2696          i <= NvKmsSurfaceMemoryFormatMax;
2697          i++) {
2698         if (nvHwFormatFromKmsFormat90(i) != 0) {
2699             pDevEvo->caps.layerCaps[NVKMS_MAIN_LAYER].supportedSurfaceMemoryFormats |=
2700                 NVBIT64(i);
2701         }
2702 
2703         if (EvoOverlayFormatFromKmsFormat91(i) != 0) {
2704             pDevEvo->caps.layerCaps[NVKMS_OVERLAY_LAYER].supportedSurfaceMemoryFormats |=
2705                 NVBIT64(i);
2706         }
2707     }
2708 
2709     EvoSetNotifierMethods90(pDevEvo,
2710                             pChannel,
2711                             TRUE /* notify */,
2712                             TRUE /* awaken */,
2713                             0    /* notifier */);
2714 
2715     /* Initialize the capability notifiers. */
2716     FOR_ALL_EVO_DISPLAYS(pDispEvo, i, pDevEvo) {
2717         nvWriteEvoCoreNotifier(pDispEvo, NV917D_CORE_NOTIFIER_3_CAPABILITIES_4,
2718                 DRF_DEF(917D_CORE_NOTIFIER_3, _CAPABILITIES_4, _DONE, _FALSE));
2719     }
2720 
2721     /* Tell the hardware to fill in the notifier. */
2722     nvDmaSetStartEvoMethod(pChannel, NV917D_GET_CAPABILITIES, 1);
2723     nvDmaSetEvoMethodData(pChannel, 0);
2724     nvDmaKickoffEvo(pChannel);
2725 
2726     FOR_ALL_EVO_DISPLAYS(pDispEvo, sd, pDevEvo) {
2727 
2728         NVEvoSubDevPtr pEvoSubDev;
2729         volatile NvU32 *pCaps;
2730 
2731         nvEvoWaitForCoreNotifier(pDispEvo, NV917D_CORE_NOTIFIER_3_CAPABILITIES_4,
2732                                  DRF_BASE(NV917D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE),
2733                                  DRF_EXTENT(NV917D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE),
2734                                  NV917D_CORE_NOTIFIER_3_CAPABILITIES_4_DONE_TRUE);
2735 
2736         pEvoSubDev = &pDevEvo->gpus[sd];
2737         pCaps = pDevEvo->core->notifiersDma[sd].subDeviceAddress[sd];
2738 
2739         nvkms_memset(&pEvoSubDev->capabilities, 0,
2740                      sizeof(pEvoSubDev->capabilities));
2741         EvoParseCapabilityNotifier3(&pEvoSubDev->capabilities, pCaps);
2742     }
2743 
2744     /* Reset notifier state so it isn't on for future updates */
2745     EvoSetNotifierMethods90(pDevEvo,
2746                             pChannel,
2747                             FALSE /* notify */,
2748                             FALSE /* awaken */,
2749                             0     /* notifier */);
2750     nvDmaKickoffEvo(pChannel);
2751 
2752     return TRUE;
2753 }
2754 
EvoSetViewportPointIn90(NVDevEvoPtr pDevEvo,const int head,NvU16 x,NvU16 y,NVEvoUpdateState * updateState)2755 static void EvoSetViewportPointIn90(NVDevEvoPtr pDevEvo, const int head,
2756                                     NvU16 x, NvU16 y,
2757                                     NVEvoUpdateState *updateState)
2758 {
2759     NVEvoChannelPtr pChannel = pDevEvo->core;
2760 
2761     /* These methods should only apply to a single pDpy */
2762     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
2763 
2764     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2765 
2766     // Set the input viewport point
2767     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_POINT_IN(head), 1);
2768     nvDmaSetEvoMethodData(pChannel, DRF_NUM(917D, _HEAD_SET_VIEWPORT_POINT_IN, _X, x) |
2769                           DRF_NUM(917D, _HEAD_SET_VIEWPORT_POINT_IN, _Y, y));
2770 }
2771 
EvoSetOutputScaler90(const NVDispEvoRec * pDispEvo,const NvU32 head,const NvU32 imageSharpeningValue,NVEvoUpdateState * updateState)2772 static void EvoSetOutputScaler90(const NVDispEvoRec *pDispEvo, const NvU32 head,
2773                                  const NvU32 imageSharpeningValue,
2774                                  NVEvoUpdateState *updateState)
2775 {
2776     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
2777     NVEvoChannelPtr pChannel = pDevEvo->core;
2778     const NVDispHeadStateEvoRec *pHeadState = &pDispEvo->headState[head];
2779     const NVHwModeViewPortEvo *pViewPort = &pHeadState->timings.viewPort;
2780     NvU32 setControlOutputScaler = 0;
2781     NvU32 vTapsHw = 0, hTapsHw = 0;
2782 
2783     /* These methods should only apply to a single pDpyEvo */
2784     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
2785 
2786     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2787     switch (pViewPort->vTaps) {
2788     case NV_EVO_SCALER_5TAPS:
2789         vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_5;
2790         break;
2791     case NV_EVO_SCALER_3TAPS:
2792         // XXX TAPS_3_ADAPTIVE instead? --> I think only allowed with interlaced
2793         vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_3;
2794         break;
2795     case NV_EVO_SCALER_2TAPS:
2796         vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_2;
2797         break;
2798     case NV_EVO_SCALER_8TAPS:
2799         nvAssert(!"Unknown pHeadState->vTaps");
2800         // fall through
2801     case NV_EVO_SCALER_1TAP:
2802         vTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_VERTICAL_TAPS_TAPS_1;
2803         break;
2804     }
2805     switch (pViewPort->hTaps) {
2806     case NV_EVO_SCALER_8TAPS:
2807         hTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_8;
2808         break;
2809     case NV_EVO_SCALER_2TAPS:
2810         hTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_2;
2811         break;
2812     case NV_EVO_SCALER_5TAPS:
2813     case NV_EVO_SCALER_3TAPS:
2814         nvAssert(!"Unknown pHeadState->hTaps");
2815         // fall through
2816     case NV_EVO_SCALER_1TAP:
2817         hTapsHw = NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER_HORIZONTAL_TAPS_TAPS_1;
2818         break;
2819     }
2820     setControlOutputScaler =
2821         DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER, _HORIZONTAL_TAPS,
2822                 hTapsHw) |
2823         DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER, _VERTICAL_TAPS,
2824                 vTapsHw);
2825 
2826     if (nvIsImageSharpeningAvailable(&pHeadState->timings.viewPort)) {
2827         setControlOutputScaler =
2828             FLD_SET_DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER,
2829                             _HRESPONSE_BIAS, imageSharpeningValue,
2830                             setControlOutputScaler);
2831 
2832         setControlOutputScaler =
2833             FLD_SET_DRF_NUM(917D, _HEAD_SET_CONTROL_OUTPUT_SCALER,
2834                             _VRESPONSE_BIAS, imageSharpeningValue,
2835                             setControlOutputScaler);
2836     }
2837 
2838     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTROL_OUTPUT_SCALER(head), 1);
2839     nvDmaSetEvoMethodData(pChannel, setControlOutputScaler);
2840 }
2841 
EvoSetViewportInOut90(NVDevEvoPtr pDevEvo,const int head,const NVHwModeViewPortEvo * pViewPortMin,const NVHwModeViewPortEvo * pViewPort,const NVHwModeViewPortEvo * pViewPortMax,NVEvoUpdateState * updateState)2842 static void EvoSetViewportInOut90(NVDevEvoPtr pDevEvo, const int head,
2843                                   const NVHwModeViewPortEvo *pViewPortMin,
2844                                   const NVHwModeViewPortEvo *pViewPort,
2845                                   const NVHwModeViewPortEvo *pViewPortMax,
2846                                   NVEvoUpdateState *updateState)
2847 {
2848     NVEvoChannelPtr pChannel = pDevEvo->core;
2849 
2850     /* These methods should only apply to a single pDpy */
2851     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
2852 
2853     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2854 
2855     /* The input viewport shouldn't vary. */
2856     nvAssert(pViewPortMin->in.width == pViewPort->in.width);
2857     nvAssert(pViewPortMax->in.width == pViewPort->in.width);
2858     nvAssert(pViewPortMin->in.height == pViewPort->in.height);
2859     nvAssert(pViewPortMax->in.height == pViewPort->in.height);
2860     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_SIZE_IN(head), 1);
2861     nvDmaSetEvoMethodData(pChannel,
2862             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_IN, _WIDTH, pViewPort->in.width) |
2863             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_IN, _HEIGHT, pViewPort->in.height));
2864 
2865     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_POINT_OUT_ADJUST(head), 1);
2866     nvDmaSetEvoMethodData(pChannel,
2867             DRF_NUM(917D, _HEAD_SET_VIEWPORT_POINT_OUT, _ADJUST_X, pViewPort->out.xAdjust) |
2868             DRF_NUM(917D, _HEAD_SET_VIEWPORT_POINT_OUT, _ADJUST_Y, pViewPort->out.yAdjust));
2869 
2870     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_SIZE_OUT(head), 1);
2871     nvDmaSetEvoMethodData(pChannel,
2872             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT, _WIDTH, pViewPort->out.width) |
2873             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT, _HEIGHT, pViewPort->out.height));
2874 
2875     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_SIZE_OUT_MIN(head), 1);
2876     nvDmaSetEvoMethodData(pChannel,
2877             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT_MIN, _WIDTH, pViewPortMin->out.width) |
2878             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT_MIN, _HEIGHT, pViewPortMin->out.height));
2879 
2880     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_VIEWPORT_SIZE_OUT_MAX(head), 1);
2881     nvDmaSetEvoMethodData(pChannel,
2882             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT_MAX, _WIDTH, pViewPortMax->out.width) |
2883             DRF_NUM(917D, _HEAD_SET_VIEWPORT_SIZE_OUT_MAX, _HEIGHT, pViewPortMax->out.height));
2884 
2885 }
2886 
2887 
2888 /*!
2889  * Compute the 917D_HEAD_SET_CONTROL_CURSOR method value.
2890  *
2891  * This function also validates that the given NVSurfaceEvoRec can be
2892  * used as a cursor image.
2893  *
2894  * Pre-nvdisplay core channel classes have the same layout of the
2895  * *7D_HEAD_SET_CONTROL_CURSOR method value.
2896 
2897  *
2898  * \param[in]  pDevEvo      The device on which the cursor will be programmed.
2899  * \param[in]  pSurfaceEvo  The surface to be used as the cursor image.
2900  * \param[out] pValue       The 917D_HEAD_SET_CONTROL_CURSOR method value.
2901 
2902  * \return  If TRUE, the surface can be used as a cursor image, and
2903  *          pValue contains the method value.  If FALSE, the surface
2904  *          cannot be used as a cursor image.
2905  */
nvEvoGetHeadSetControlCursorValue90(const NVDevEvoRec * pDevEvo,const NVSurfaceEvoRec * pSurfaceEvo,NvU32 * pValue)2906 NvBool nvEvoGetHeadSetControlCursorValue90(const NVDevEvoRec *pDevEvo,
2907                                            const NVSurfaceEvoRec *pSurfaceEvo,
2908                                            NvU32 *pValue)
2909 {
2910     NvU32 value = 0;
2911 
2912     if (pSurfaceEvo == NULL) {
2913         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _ENABLE, _DISABLE);
2914         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _FORMAT, _A8R8G8B8);
2915         goto done;
2916     } else {
2917         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _ENABLE, _ENABLE);
2918     }
2919 
2920     /* The cursor must always be pitch. */
2921 
2922     if (pSurfaceEvo->layout != NvKmsSurfaceMemoryLayoutPitch) {
2923         return FALSE;
2924     }
2925 
2926     /*
2927      * The only supported cursor image memory format is A8R8G8B8.
2928      */
2929     if (pSurfaceEvo->format == NvKmsSurfaceMemoryFormatA8R8G8B8) {
2930         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _FORMAT, _A8R8G8B8);
2931     } else {
2932         return FALSE;
2933     }
2934 
2935     /*
2936      * The cursor only supports a few image sizes.
2937      */
2938     if ((pSurfaceEvo->widthInPixels == 32) &&
2939         (pSurfaceEvo->heightInPixels == 32)) {
2940         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _SIZE, _W32_H32);
2941     } else if ((pSurfaceEvo->widthInPixels == 64) &&
2942                (pSurfaceEvo->heightInPixels == 64)) {
2943         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _SIZE, _W64_H64);
2944     } else if ((pDevEvo->cursorHal->caps.maxSize >= 128) &&
2945                (pSurfaceEvo->widthInPixels == 128) &&
2946                (pSurfaceEvo->heightInPixels == 128)) {
2947         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _SIZE, _W128_H128);
2948     } else if ((pDevEvo->cursorHal->caps.maxSize >= 256) &&
2949                (pSurfaceEvo->widthInPixels == 256) &&
2950                (pSurfaceEvo->heightInPixels == 256)) {
2951         value |= DRF_DEF(927D, _HEAD_SET_CONTROL_CURSOR, _SIZE, _W256_H256);
2952     } else {
2953         return FALSE;
2954     }
2955 
2956     /*
2957      * Hard code the cursor hotspot.
2958      */
2959     value |= DRF_NUM(927D, _HEAD_SET_CONTROL_CURSOR, _HOT_SPOT_Y, 0);
2960     value |= DRF_NUM(927D, _HEAD_SET_CONTROL_CURSOR, _HOT_SPOT_X, 0);
2961 
2962 done:
2963 
2964     if (pValue != NULL) {
2965         *pValue = value;
2966     }
2967 
2968     return TRUE;
2969 }
2970 
EvoSetCursorImage(NVDevEvoPtr pDevEvo,const int head,const NVSurfaceEvoRec * pSurfaceEvo,NVEvoUpdateState * updateState,const struct NvKmsCompositionParams * pCursorCompParams)2971 static void EvoSetCursorImage(NVDevEvoPtr pDevEvo, const int head,
2972                               const NVSurfaceEvoRec *pSurfaceEvo,
2973                               NVEvoUpdateState *updateState,
2974                               const struct NvKmsCompositionParams *pCursorCompParams)
2975 {
2976     NVEvoChannelPtr pChannel = pDevEvo->core;
2977     const NvU32 ctxdma = pSurfaceEvo ? pSurfaceEvo->planes[0].surfaceDesc.ctxDmaHandle : 0;
2978     const NvU64 offset = pSurfaceEvo ? pSurfaceEvo->planes[0].offset : 0;
2979     NvU32 headSetControlCursorValue = 0;
2980     NvBool ret;
2981 
2982     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
2983 
2984     /* These methods should only apply to a single pDpy */
2985     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
2986     nvAssert(pCursorCompParams->colorKeySelect ==
2987                 NVKMS_COMPOSITION_COLOR_KEY_SELECT_DISABLE);
2988     nvAssert(NVBIT(pCursorCompParams->blendingMode[1]) &
2989                 NV_EVO2_SUPPORTED_CURSOR_COMP_BLEND_MODES);
2990     nvAssert(!pSurfaceEvo || ctxdma);
2991 
2992     ret = nvEvoGetHeadSetControlCursorValue90(pDevEvo, pSurfaceEvo,
2993                                               &headSetControlCursorValue);
2994     /*
2995      * The caller should have already validated the surface, so there
2996      * shouldn't be a failure.
2997      */
2998     if (!ret) {
2999         nvAssert(!"Could not construct HEAD_SET_CONTROL_CURSOR value");
3000     }
3001 
3002     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_PRESENT_CONTROL_CURSOR(head), 1);
3003     nvDmaSetEvoMethodData(pChannel,
3004             DRF_DEF(917D, _HEAD_SET_PRESENT_CONTROL_CURSOR, _MODE, _MONO));
3005 
3006     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_OFFSETS_CURSOR(head, 0), 4);
3007     // The cursor has its own context DMA.
3008     nvDmaSetEvoMethodData(pChannel,
3009         DRF_NUM(917D, _HEAD_SET_OFFSETS_CURSOR, _ORIGIN,
3010                 nvCtxDmaOffsetFromBytes(offset)));
3011     nvDmaSetEvoMethodData(pChannel,
3012         DRF_NUM(917D, _HEAD_SET_OFFSETS_CURSOR, _ORIGIN,
3013                 nvCtxDmaOffsetFromBytes(offset)));
3014     nvDmaSetEvoMethodData(pChannel,
3015             DRF_NUM(917D, _HEAD_SET_CONTEXT_DMAS_CURSOR, _HANDLE, ctxdma));
3016     // Always set the right cursor context DMA.
3017     // HW will just ignore this if it is not in stereo cursor mode.
3018     nvDmaSetEvoMethodData(pChannel,
3019             DRF_NUM(917D, _HEAD_SET_CONTEXT_DMAS_CURSOR, _HANDLE, ctxdma));
3020 
3021     switch (pCursorCompParams->blendingMode[1]) {
3022     case NVKMS_COMPOSITION_BLENDING_MODE_NON_PREMULT_ALPHA:
3023         headSetControlCursorValue |=
3024             DRF_DEF(917D, _HEAD_SET_CONTROL_CURSOR, _COMPOSITION, _ALPHA_BLEND);
3025         break;
3026     case NVKMS_COMPOSITION_BLENDING_MODE_PREMULT_ALPHA:
3027         headSetControlCursorValue |=
3028             DRF_DEF(917D, _HEAD_SET_CONTROL_CURSOR, _COMPOSITION, _PREMULT_ALPHA_BLEND);
3029         break;
3030     default:
3031         nvEvoLogDevDebug(pDevEvo, EVO_LOG_ERROR,
3032             "%s: composition mode %d not supported for cursor",
3033             __func__, pCursorCompParams->blendingMode[1]);
3034     }
3035 
3036     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTROL_CURSOR(head), 1);
3037     nvDmaSetEvoMethodData(pChannel, headSetControlCursorValue);
3038 }
3039 
EvoSetCursorImage91(NVDevEvoPtr pDevEvo,const int head,const NVSurfaceEvoRec * pSurfaceEvo,NVEvoUpdateState * updateState,const struct NvKmsCompositionParams * pCursorCompParams)3040 static void EvoSetCursorImage91(NVDevEvoPtr pDevEvo, const int head,
3041                                 const NVSurfaceEvoRec *pSurfaceEvo,
3042                                 NVEvoUpdateState *updateState,
3043                                 const struct NvKmsCompositionParams *pCursorCompParams)
3044 {
3045     NvU32 sd;
3046 
3047     for (sd = 0;  sd < pDevEvo->numSubDevices; sd++) {
3048         if (!((nvPeekEvoSubDevMask(pDevEvo) & (1 << sd)))) {
3049             continue;
3050         }
3051 
3052         /*
3053          * Set up the cursor surface: a cursor surface is allowed only if
3054          * there's a non-NULL ISO ctxdma.
3055          */
3056         if (pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head] == NULL &&
3057             pSurfaceEvo != NULL) {
3058             continue;
3059         }
3060 
3061         nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
3062         EvoSetCursorImage(pDevEvo,
3063                           head,
3064                           pSurfaceEvo,
3065                           updateState,
3066                           pCursorCompParams);
3067         nvPopEvoSubDevMask(pDevEvo);
3068     }
3069 }
3070 
EvoValidateCursorSurface90(const NVDevEvoRec * pDevEvo,const NVSurfaceEvoRec * pSurfaceEvo)3071 static NvBool EvoValidateCursorSurface90(const NVDevEvoRec *pDevEvo,
3072                                          const NVSurfaceEvoRec *pSurfaceEvo)
3073 {
3074     return nvEvoGetHeadSetControlCursorValue90(pDevEvo, pSurfaceEvo, NULL);
3075 }
3076 
3077 /*
3078  * The 'sourceFetchRect' parameter is ignored by this function because there are
3079  * no format-dependent restrictions for the source fetch rectangle on EVO.
3080  */
EvoValidateWindowFormat90(const enum NvKmsSurfaceMemoryFormat format,const struct NvKmsRect * sourceFetchRect,NvU32 * hwFormatOut)3081 static NvBool EvoValidateWindowFormat90(
3082     const enum NvKmsSurfaceMemoryFormat format,
3083     const struct NvKmsRect *sourceFetchRect,
3084     NvU32 *hwFormatOut)
3085 {
3086     const NvU32 hwFormat = nvHwFormatFromKmsFormat90(format);
3087 
3088     if (hwFormat == 0) {
3089         return FALSE;
3090     }
3091 
3092     if (hwFormatOut != NULL) {
3093         *hwFormatOut = hwFormat;
3094     }
3095 
3096     return TRUE;
3097 }
3098 
EvoInitCompNotifier3(const NVDispEvoRec * pDispEvo,int idx)3099 static void EvoInitCompNotifier3(const NVDispEvoRec *pDispEvo, int idx)
3100 {
3101     nvWriteEvoCoreNotifier(pDispEvo, NV917D_CORE_NOTIFIER_3_COMPLETION_0 + idx,
3102                            DRF_DEF(917D_CORE_NOTIFIER_3, _COMPLETION_0, _DONE, _FALSE));
3103 }
3104 
EvoIsCompNotifierComplete3(NVDispEvoPtr pDispEvo,int idx)3105 static NvBool EvoIsCompNotifierComplete3(NVDispEvoPtr pDispEvo, int idx) {
3106     return nvEvoIsCoreNotifierComplete(pDispEvo,
3107                                        NV917D_CORE_NOTIFIER_3_COMPLETION_0 + idx,
3108                                        DRF_BASE(NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE),
3109                                        DRF_EXTENT(NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE),
3110                                        NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE_TRUE);
3111 }
3112 
EvoWaitForCompNotifier3(const NVDispEvoRec * pDispEvo,int idx)3113 static void EvoWaitForCompNotifier3(const NVDispEvoRec *pDispEvo, int idx)
3114 {
3115     nvEvoWaitForCoreNotifier(pDispEvo, NV917D_CORE_NOTIFIER_3_COMPLETION_0 + idx,
3116                              DRF_BASE(NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE),
3117                              DRF_EXTENT(NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE),
3118                              NV917D_CORE_NOTIFIER_3_COMPLETION_0_DONE_TRUE);
3119 }
3120 
EvoSetDither91(NVDispEvoPtr pDispEvo,const int head,const NvBool enabled,const NvU32 type,const NvU32 algo,NVEvoUpdateState * updateState)3121 static void EvoSetDither91(NVDispEvoPtr pDispEvo, const int head,
3122                            const NvBool enabled, const NvU32 type,
3123                            const NvU32 algo,
3124                            NVEvoUpdateState *updateState)
3125 {
3126     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
3127     NVEvoChannelPtr pChannel = pDevEvo->core;
3128     NvU32 ditherControl;
3129 
3130     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
3131 
3132     if (enabled) {
3133         ditherControl = DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _ENABLE, _ENABLE);
3134 
3135         switch (type) {
3136         case NV0073_CTRL_SPECIFIC_OR_DITHER_TYPE_6_BITS:
3137             ditherControl |=
3138                 DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _BITS, _DITHER_TO_6_BITS);
3139             break;
3140         case NV0073_CTRL_SPECIFIC_OR_DITHER_TYPE_8_BITS:
3141             ditherControl |=
3142                 DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _BITS, _DITHER_TO_8_BITS);
3143             break;
3144         default:
3145             nvAssert(!"Unknown ditherType");
3146             // Fall through
3147         case NV0073_CTRL_SPECIFIC_OR_DITHER_TYPE_OFF:
3148             ditherControl = NV917D_HEAD_SET_DITHER_CONTROL_ENABLE_DISABLE;
3149             break;
3150         }
3151 
3152     } else {
3153         ditherControl = DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _ENABLE, _DISABLE);
3154     }
3155 
3156     switch (algo) {
3157     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_STATIC_ERR_ACC:
3158         ditherControl |=
3159             DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _MODE, _STATIC_ERR_ACC);
3160         break;
3161     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_DYNAMIC_2X2:
3162         ditherControl |=
3163             DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _MODE, _DYNAMIC_2X2);
3164         break;
3165     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_STATIC_2X2:
3166         ditherControl |=
3167             DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _MODE, _STATIC_2X2);
3168         break;
3169     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_TEMPORAL:
3170         ditherControl |=
3171             DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _MODE, _TEMPORAL);
3172         break;
3173     default:
3174         nvAssert(!"Unknown DitherAlgo");
3175         // Fall through
3176     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_UNKNOWN:
3177     case NV0073_CTRL_SPECIFIC_OR_DITHER_ALGO_DYNAMIC_ERR_ACC:
3178         ditherControl |=
3179             DRF_DEF(917D, _HEAD_SET_DITHER_CONTROL, _MODE, _DYNAMIC_ERR_ACC);
3180         break;
3181     }
3182 
3183     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_DITHER_CONTROL(head), 1);
3184     nvDmaSetEvoMethodData(pChannel, ditherControl);
3185 }
3186 
EvoSetStallLock94(NVDispEvoPtr pDispEvo,const int head,NvBool enable,NVEvoUpdateState * updateState)3187 static void EvoSetStallLock94(NVDispEvoPtr pDispEvo, const int head,
3188                               NvBool enable, NVEvoUpdateState *updateState)
3189 {
3190     NVDevEvoPtr pDevEvo = pDispEvo->pDevEvo;
3191     NVEvoChannelPtr pChannel = pDevEvo->core;
3192 
3193     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
3194 
3195     if (enable) {
3196         nvDmaSetStartEvoMethod(pChannel, NV947D_HEAD_SET_STALL_LOCK(head), 1);
3197         nvDmaSetEvoMethodData(pChannel,
3198             DRF_DEF(947D, _HEAD_SET_STALL_LOCK, _ENABLE, _TRUE) |
3199             DRF_DEF(947D, _HEAD_SET_STALL_LOCK, _MODE, _ONE_SHOT) |
3200             DRF_DEF(947D, _HEAD_SET_STALL_LOCK, _LOCK_PIN, _UNSPECIFIED) |
3201             DRF_DEF(947D, _HEAD_SET_STALL_LOCK, _UNSTALL_MODE, _LINE_LOCK));
3202     } else {
3203         nvDmaSetStartEvoMethod(pChannel, NV947D_HEAD_SET_STALL_LOCK(head), 1);
3204         nvDmaSetEvoMethodData(pChannel,
3205             DRF_DEF(947D, _HEAD_SET_STALL_LOCK, _ENABLE, _FALSE));
3206     }
3207 }
3208 
ForceIdleBaseChannel(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NvU32 sd)3209 static NvBool ForceIdleBaseChannel(
3210     NVDevEvoPtr pDevEvo,
3211     NVEvoChannelPtr pChannel,
3212     NvU32 sd)
3213 {
3214     NV5070_CTRL_CMD_STOP_BASE_PARAMS stopParams = { };
3215     NvNotification *pNotifyData = pChannel->notifiersDma[sd].subDeviceAddress[sd];
3216     NvU64 startTime = 0;
3217     const NvU32 timeout = 2000000; // 2 seconds
3218     NvU32 ret;
3219 
3220     nvAssert((pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL) != 0);
3221 
3222     pNotifyData->status = NV5070_NOTIFICATION_STATUS_IN_PROGRESS;
3223 
3224     stopParams.base.subdeviceIndex = sd;
3225     stopParams.channelInstance = pChannel->instance;
3226     stopParams.notifyMode = NV5070_CTRL_CMD_STOP_BASE_NOTIFY_MODE_WRITE;
3227     stopParams.hNotifierCtxDma = pChannel->notifiersDma[sd].surfaceDesc.ctxDmaHandle;
3228     stopParams.offset = 0;
3229     stopParams.hEvent = 0;
3230 
3231     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
3232                          pDevEvo->displayHandle,
3233                          NV5070_CTRL_CMD_STOP_BASE,
3234                          &stopParams, sizeof(stopParams));
3235     if (ret != NVOS_STATUS_SUCCESS) {
3236         nvAssert(!"STOP_BASE failed");
3237         return FALSE;
3238     }
3239 
3240     do {
3241         if (pNotifyData->status == NV5070_NOTIFICATION_STATUS_DONE_SUCCESS) {
3242             break;
3243         }
3244 
3245         if (nvExceedsTimeoutUSec(pDevEvo, &startTime, timeout)) {
3246             nvAssert(!"STOP_BASE timed out");
3247             return FALSE;
3248         }
3249 
3250         nvkms_yield();
3251 
3252     } while (TRUE);
3253 
3254     return TRUE;
3255 }
3256 
ForceIdleOverlayChannel(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NvU32 sd)3257 static NvBool ForceIdleOverlayChannel(
3258     NVDevEvoPtr pDevEvo,
3259     NVEvoChannelPtr pChannel,
3260     NvU32 sd)
3261 {
3262     NV5070_CTRL_CMD_STOP_OVERLAY_PARAMS stopParams = { };
3263     NvNotification *pNotifyData = pChannel->notifiersDma[sd].subDeviceAddress[sd];
3264     NvU64 startTime = 0;
3265     const NvU32 timeout = 2000000; // 2 seconds
3266     NvU32 ret;
3267 
3268     nvAssert((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0);
3269 
3270     pNotifyData->status = NV5070_NOTIFICATION_STATUS_IN_PROGRESS;
3271 
3272     stopParams.base.subdeviceIndex = sd;
3273     stopParams.channelInstance = pChannel->instance;
3274     stopParams.notifyMode = NV5070_CTRL_CMD_STOP_OVERLAY_NOTIFY_MODE_WRITE;
3275     stopParams.hNotifierCtxDma = pChannel->notifiersDma[sd].surfaceDesc.ctxDmaHandle;
3276     stopParams.offset = 0;
3277     stopParams.hEvent = 0;
3278 
3279     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
3280                          pDevEvo->displayHandle,
3281                          NV5070_CTRL_CMD_STOP_OVERLAY,
3282                          &stopParams, sizeof(stopParams));
3283     if (ret != NVOS_STATUS_SUCCESS) {
3284         nvAssert(!"STOP_OVERLAY failed");
3285         return FALSE;
3286     }
3287 
3288     do {
3289         if (pNotifyData->status == NV5070_NOTIFICATION_STATUS_DONE_SUCCESS) {
3290             break;
3291         }
3292 
3293         if (nvExceedsTimeoutUSec(pDevEvo, &startTime, timeout)) {
3294             nvAssert(!"STOP_OVERLAY timed out");
3295             return FALSE;
3296         }
3297 
3298         nvkms_yield();
3299 
3300     } while (TRUE);
3301 
3302     return TRUE;
3303 }
3304 
EvoForceIdleSatelliteChannel90(NVDevEvoPtr pDevEvo,const NVEvoIdleChannelState * idleChannelState)3305 static NvBool EvoForceIdleSatelliteChannel90(
3306     NVDevEvoPtr pDevEvo,
3307     const NVEvoIdleChannelState *idleChannelState)
3308 {
3309     NvU32 head, sd;
3310     NvBool ret = TRUE;
3311 
3312     for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
3313         /*
3314          * Forcing a channel to be idle is currently only implemented for
3315          * base.
3316          */
3317         if ((idleChannelState->subdev[sd].channelMask &
3318              ~(NV_EVO_CHANNEL_MASK_BASE_ALL |
3319                NV_EVO_CHANNEL_MASK_OVERLAY_ALL)) != 0) {
3320 
3321             nvEvoLogDevDebug(pDevEvo, EVO_LOG_ERROR,
3322                 "Forcing channel idle only implemented for base and overlay");
3323             return FALSE;
3324         }
3325 
3326         for (head = 0; head < pDevEvo->numHeads; head++) {
3327             const NVEvoChannelMask thisBaseMask =
3328                 DRF_IDX_DEF64(_EVO, _CHANNEL_MASK, _BASE, head, _ENABLE);
3329             const NVEvoChannelMask thisOverlayMask =
3330                 DRF_IDX_DEF64(_EVO, _CHANNEL_MASK, _OVERLAY, head, _ENABLE);
3331 
3332             if (idleChannelState->subdev[sd].channelMask &
3333                 thisBaseMask) {
3334 
3335                 NVEvoChannelPtr pBaseChannel = pDevEvo->base[head];
3336 
3337                 if (!ForceIdleBaseChannel(pDevEvo, pBaseChannel, sd)) {
3338                     ret = FALSE;
3339                 }
3340             }
3341 
3342             if (idleChannelState->subdev[sd].channelMask &
3343                 thisOverlayMask) {
3344 
3345                 NVEvoChannelPtr pOverlayChannel = pDevEvo->overlay[head];
3346 
3347                 if (!ForceIdleOverlayChannel(pDevEvo, pOverlayChannel, sd)) {
3348                     ret = FALSE;
3349                 }
3350             }
3351         }
3352     }
3353 
3354     return ret;
3355 }
3356 
EvoAllocRmCtrlObject90(NVDevEvoPtr pDevEvo)3357 static NvBool EvoAllocRmCtrlObject90(NVDevEvoPtr pDevEvo)
3358 {
3359     /* Nothing to do for pre-nvdisplay */
3360     return TRUE;
3361 }
3362 
EvoFreeRmCtrlObject90(NVDevEvoPtr pDevEvo)3363 static void EvoFreeRmCtrlObject90(NVDevEvoPtr pDevEvo)
3364 {
3365     /* Nothing to do for pre-nvdisplay */
3366 }
3367 
EvoSetImmPointOut91(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NvU32 sd,NVEvoUpdateState * updateState,NvU16 x,NvU16 y)3368 static void EvoSetImmPointOut91(NVDevEvoPtr pDevEvo,
3369                                 NVEvoChannelPtr pChannel,
3370                                 NvU32 sd,
3371                                 NVEvoUpdateState *updateState,
3372                                 NvU16 x, NvU16 y)
3373 {
3374     GK104DispOverlayImmControlPio *pOverlayImm =
3375         pChannel->imm.u.pio->control[sd];
3376 
3377     /* The only immediate channel we have is overlay. */
3378     nvAssert((pChannel->channelMask & NV_EVO_CHANNEL_MASK_OVERLAY_ALL) != 0);
3379     nvAssert(pChannel->imm.type == NV_EVO_IMM_CHANNEL_PIO);
3380     nvAssert(pOverlayImm != NULL);
3381 
3382     /* Left eye */
3383     pOverlayImm->SetPointsOut[0] =
3384         DRF_NUM(917B, _SET_POINTS_OUT, _X, x) |
3385         DRF_NUM(917B, _SET_POINTS_OUT, _Y, y);
3386 
3387     pOverlayImm->Update =
3388         DRF_DEF(917B, _UPDATE, _INTERLOCK_WITH_CORE, _DISABLE);
3389 }
3390 
EvoStartHeadCRC32Capture90(NVDevEvoPtr pDevEvo,NVEvoDmaPtr pDma,NVConnectorEvoPtr pConnectorEvo,const enum nvKmsTimingsProtocol protocol,const NvU32 orIndex,NvU32 head,NvU32 sd,NVEvoUpdateState * updateState)3391 static void EvoStartHeadCRC32Capture90(NVDevEvoPtr pDevEvo,
3392                                        NVEvoDmaPtr pDma,
3393                                        NVConnectorEvoPtr pConnectorEvo,
3394                                        const enum nvKmsTimingsProtocol protocol,
3395                                        const NvU32 orIndex,
3396                                        NvU32 head,
3397                                        NvU32 sd,
3398                                        NVEvoUpdateState *updateState)
3399 {
3400     NVEvoChannelPtr pChannel = pDevEvo->core;
3401     NvU32 dmaCtx = pDma->surfaceDesc.ctxDmaHandle;
3402     NvU32 orOutput = 0;
3403 
3404     /* These method should only apply to a single pDpy */
3405     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
3406 
3407     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
3408 
3409     switch (pConnectorEvo->or.type) {
3410     case NV0073_CTRL_SPECIFIC_OR_TYPE_DAC:
3411         orOutput =
3412             NV917D_HEAD_SET_CRC_CONTROL_PRIMARY_OUTPUT_DAC(orIndex);
3413         break;
3414     case NV0073_CTRL_SPECIFIC_OR_TYPE_SOR:
3415         if (protocol == NVKMS_PROTOCOL_SOR_DP_A ||
3416             protocol == NVKMS_PROTOCOL_SOR_DP_B) {
3417             orOutput =
3418                 NV917D_HEAD_SET_CRC_CONTROL_PRIMARY_OUTPUT_SF(head);
3419         } else {
3420             orOutput =
3421                 NV917D_HEAD_SET_CRC_CONTROL_PRIMARY_OUTPUT_SOR(orIndex);
3422         }
3423         break;
3424     case NV0073_CTRL_SPECIFIC_OR_TYPE_PIOR:
3425         orOutput =
3426             NV917D_HEAD_SET_CRC_CONTROL_PRIMARY_OUTPUT_PIOR(orIndex);
3427         break;
3428     default:
3429         nvAssert(!"Invalid pConnectorEvo->or.type");
3430         break;
3431     }
3432 
3433     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTEXT_DMA_CRC(head), 1);
3434     nvDmaSetEvoMethodData(pChannel,
3435             DRF_NUM(917D, _HEAD_SET_CONTEXT_DMA_CRC, _HANDLE, dmaCtx));
3436 
3437     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CRC_CONTROL(head), 1);
3438     nvDmaSetEvoMethodData(pChannel,
3439         DRF_NUM(917D, _HEAD_SET_CRC_CONTROL, _PRIMARY_OUTPUT, orOutput) |
3440         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _SECONDARY_OUTPUT, _NONE) |
3441         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _CONTROLLING_CHANNEL, _CORE) |
3442         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _EXPECT_BUFFER_COLLAPSE, _FALSE) |
3443         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _TIMESTAMP_MODE, _FALSE) |
3444         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _FLIPLOCK_MODE, _FALSE) |
3445         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _CRC_DURING_SNOOZE, _DISABLE));
3446 
3447     /* Reset the CRC notifier */
3448     nvEvoResetCRC32Notifier(pDma->subDeviceAddress[sd],
3449                             NV917D_NOTIFIER_CRC_1_STATUS_0,
3450                             DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_DONE),
3451                             NV917D_NOTIFIER_CRC_1_STATUS_0_DONE_FALSE);
3452 }
3453 
EvoStopHeadCRC32Capture90(NVDevEvoPtr pDevEvo,NvU32 head,NVEvoUpdateState * updateState)3454 static void EvoStopHeadCRC32Capture90(NVDevEvoPtr pDevEvo,
3455                                       NvU32 head,
3456                                       NVEvoUpdateState *updateState)
3457 {
3458     NVEvoChannelPtr pChannel = pDevEvo->core;
3459 
3460     /* These method should only apply to a single pDpy */
3461     nvAssert(pDevEvo->subDevMaskStackDepth > 0);
3462 
3463     nvUpdateUpdateState(pDevEvo, updateState, pChannel);
3464 
3465     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CONTEXT_DMA_CRC(head), 1);
3466     nvDmaSetEvoMethodData(pChannel, 0);
3467 
3468     nvDmaSetStartEvoMethod(pChannel, NV917D_HEAD_SET_CRC_CONTROL(head), 1);
3469     nvDmaSetEvoMethodData(pChannel,
3470         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _PRIMARY_OUTPUT, _NONE) |
3471         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _SECONDARY_OUTPUT, _NONE) |
3472         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _CONTROLLING_CHANNEL, _CORE) |
3473         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _EXPECT_BUFFER_COLLAPSE, _FALSE) |
3474         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _TIMESTAMP_MODE, _FALSE) |
3475         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _FLIPLOCK_MODE, _FALSE) |
3476         DRF_DEF(917D, _HEAD_SET_CRC_CONTROL, _CRC_DURING_SNOOZE, _DISABLE));
3477 }
3478 
3479 /*!
3480  * Queries the current head's CRC Notifier and returns values if successful
3481  *
3482  * First waits for hardware to finish writing to the CRC32Notifier,
3483  * and performs a read of the Compositor and SF/OR CRCs in numCRC32 frames
3484  * Crc fields in input array crc32 should be calloc'd to 0s.
3485  *
3486  * \param[in]  pDevEvo          NVKMS device pointer
3487  * \param[in]  pDma             Pointer to DMA-mapped memory
3488  * \param[in]  sd               Subdevice index
3489  * \param[in]  entry_count      Number of independent frames to read CRCs from
3490  * \param[out] crc32            Contains pointers to CRC output arrays
3491  * \param[out] numCRC32         Number of CRC frames successfully read from DMA
3492  *
3493  * \return  Returns TRUE if was able to successfully read CRCs from DMA,
3494  *          otherwise FALSE
3495  */
EvoQueryHeadCRC32_90(NVDevEvoPtr pDevEvo,NVEvoDmaPtr pDma,NvU32 sd,NvU32 entry_count,CRC32NotifierCrcOut * crc32,NvU32 * numCRC32)3496 static NvBool EvoQueryHeadCRC32_90(NVDevEvoPtr pDevEvo,
3497                                    NVEvoDmaPtr pDma,
3498                                    NvU32 sd,
3499                                    NvU32 entry_count,
3500                                    CRC32NotifierCrcOut *crc32,
3501                                    NvU32 *numCRC32)
3502 {
3503     volatile NvU32 *pCRC32Notifier = pDma->subDeviceAddress[sd];
3504     const NvU32 entry_stride =
3505           NV917D_NOTIFIER_CRC_1_CRC_ENTRY1_8 - NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_4;
3506     // Define how many/which variables to read from each CRCNotifierEntry struct
3507     const CRC32NotifierEntryRec field_info[NV_EVO2_NUM_CRC_FIELDS] = {
3508         {
3509             .field_offset = NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_3,
3510             .field_base_bit =
3511              DRF_BASE(NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_3_COMPOSITOR_CRC),
3512             .field_extent_bit =
3513              DRF_EXTENT(NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_3_COMPOSITOR_CRC),
3514             .field_frame_values = crc32->compositorCrc32
3515         },
3516         {
3517             .field_offset = NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_4,
3518             .field_base_bit =
3519              DRF_BASE(NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_4_PRIMARY_OUTPUT_CRC),
3520             .field_extent_bit =
3521              DRF_EXTENT(NV917D_NOTIFIER_CRC_1_CRC_ENTRY0_4_PRIMARY_OUTPUT_CRC),
3522             .field_frame_values = crc32->outputCrc32
3523         }
3524     };
3525     const CRC32NotifierEntryFlags flag_info[NV_EVO2_NUM_CRC_FLAGS] = {
3526         {
3527             .flag_base_bit =
3528              DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_COUNT),
3529             .flag_extent_bit =
3530              DRF_EXTENT(NV917D_NOTIFIER_CRC_1_STATUS_0_COUNT),
3531             .flag_type = NVEvoCrc32NotifierFlagCount
3532         },
3533         {
3534             .flag_base_bit =
3535              DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_COMPOSITOR_OVERFLOW),
3536             .flag_extent_bit =
3537              DRF_EXTENT(NV917D_NOTIFIER_CRC_1_STATUS_0_COMPOSITOR_OVERFLOW),
3538             .flag_type = NVEvoCrc32NotifierFlagCrcOverflow
3539         },
3540         {
3541             .flag_base_bit =
3542              DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_PRIMARY_OUTPUT_OVERFLOW),
3543             .flag_extent_bit =
3544              DRF_EXTENT(NV917D_NOTIFIER_CRC_1_STATUS_0_PRIMARY_OUTPUT_OVERFLOW),
3545             .flag_type = NVEvoCrc32NotifierFlagCrcOverflow
3546         }
3547     };
3548 
3549     if (!nvEvoWaitForCRC32Notifier(pDevEvo,
3550                                    pCRC32Notifier,
3551                                    NV917D_NOTIFIER_CRC_1_STATUS_0,
3552                                    DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_DONE),
3553                                    DRF_EXTENT(NV917D_NOTIFIER_CRC_1_STATUS_0_DONE),
3554                                    NV917D_NOTIFIER_CRC_1_STATUS_0_DONE_TRUE)) {
3555         return FALSE;
3556     }
3557 
3558     *numCRC32 = nvEvoReadCRC32Notifier(pCRC32Notifier,
3559                                        entry_stride,
3560                                        entry_count,
3561                                        NV917D_NOTIFIER_CRC_1_STATUS_0, /* Status offset */
3562                                        NV_EVO2_NUM_CRC_FIELDS,
3563                                        NV_EVO2_NUM_CRC_FLAGS,
3564                                        field_info,
3565                                        flag_info);
3566 
3567 
3568     nvEvoResetCRC32Notifier(pCRC32Notifier,
3569                             NV917D_NOTIFIER_CRC_1_STATUS_0,
3570                             DRF_BASE(NV917D_NOTIFIER_CRC_1_STATUS_0_DONE),
3571                             NV917D_NOTIFIER_CRC_1_STATUS_0_DONE_FALSE);
3572 
3573     return TRUE;
3574 }
3575 
EvoGetScanLine90(const NVDispEvoRec * pDispEvo,const NvU32 head,NvU16 * pScanLine,NvBool * pInBlankingPeriod)3576 static void EvoGetScanLine90(const NVDispEvoRec *pDispEvo,
3577                              const NvU32 head,
3578                              NvU16 *pScanLine,
3579                              NvBool *pInBlankingPeriod)
3580 {
3581     const NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
3582     const NvU32 sd = pDispEvo->displayOwner;
3583     const void *pDma = pDevEvo->base[head]->pb.control[sd];
3584     NvU32 scanLine = nvDmaLoadPioMethod(pDma, NV917C_GET_SCANLINE);
3585 
3586     /*
3587      * This method immediately returns the value of the scanline currently being
3588      * read by the DMI.  This method is a channel method so it operates
3589      * completely asynchronously from the processing of methods in the
3590      * pushbuffer. A negative value indicate that the DMI is in vertical
3591      * blanking. Note that this is a PIO method that executes immediately. The
3592      * coding of this value is as follows:
3593      * If Line[15] == 0 (positive value)
3594      *   then Line[14:0] is the post-aa resolved line currently being read by
3595      *   the DMI.
3596      * If Line[15] == 1 (negative value)
3597      *   then Line[14:0] is the number of microseconds remaining in the vertical
3598      *   blanking interval.
3599      * Examples:
3600      *   Line = 0x0192 - DMI is reading line 402 of the current buffer.
3601      *   Line = 0x8023 - DMI is 35 uS from the end of vertical blanking.
3602      */
3603 
3604     if ((scanLine & NVBIT(15)) == 0) {
3605         *pInBlankingPeriod = FALSE;
3606         *pScanLine = scanLine & DRF_MASK(14:0);
3607     } else {
3608         *pInBlankingPeriod = TRUE;
3609     }
3610 }
3611 
EvoGetActiveViewportOffset94(NVDispEvoRec * pDispEvo,NvU32 head)3612 static NvU32 EvoGetActiveViewportOffset94(NVDispEvoRec *pDispEvo, NvU32 head)
3613 {
3614     NV5070_CTRL_CMD_GET_ACTIVE_VIEWPORT_BASE_PARAMS params = { };
3615     NvU32 ret;
3616     NVDevEvoRec *pDevEvo = pDispEvo->pDevEvo;
3617 
3618     params.base.subdeviceIndex = pDispEvo->displayOwner;
3619     params.head = head;
3620 
3621     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
3622                          pDevEvo->displayHandle,
3623                          NV5070_CTRL_CMD_GET_ACTIVE_VIEWPORT_BASE,
3624                          &params, sizeof(params));
3625 
3626     if (ret != NVOS_STATUS_SUCCESS) {
3627         nvEvoLogDevDebug(pDevEvo, EVO_LOG_ERROR,
3628                          "Failed to query active viewport offset");
3629     }
3630 
3631     return params.activeViewportBase;
3632 }
3633 
3634 static void
EvoClearSurfaceUsage91(NVDevEvoPtr pDevEvo,NVSurfaceEvoPtr pSurfaceEvo)3635 EvoClearSurfaceUsage91(NVDevEvoPtr pDevEvo, NVSurfaceEvoPtr pSurfaceEvo)
3636 {
3637     NvU32 sd;
3638     NvBool kickOff = FALSE;
3639     NVEvoUpdateState updateState = { };
3640 
3641     for (sd = 0; sd < pDevEvo->numSubDevices; sd++) {
3642         NvU32 head;
3643 
3644         for (head = 0; head < pDevEvo->numHeads; head++) {
3645             const struct NvKmsCscMatrix zeroCscMatrix = { };
3646             const NVEvoSubDevHeadStateRec *pSdHeadState =
3647                 &pDevEvo->gpus[sd].headState[head];
3648 
3649             /*
3650              * In background, if the given surface is used for the core surface
3651              * programming to satisfy the EVO hardware constraints then clear
3652              * that usage. Reuse the client specified base surface for the core
3653              * channel programming.
3654              */
3655             if (pSurfaceEvo !=
3656                 pDevEvo->pSubDevices[sd]->pCoreChannelSurface[head]) {
3657                 continue;
3658             }
3659 
3660             nvPushEvoSubDevMask(pDevEvo, NVBIT(sd));
3661             EvoPushSetCoreSurfaceMethodsForOneSd(pDevEvo, sd, head,
3662                 pSdHeadState->layer[NVKMS_MAIN_LAYER].pSurfaceEvo[NVKMS_LEFT],
3663                 &zeroCscMatrix, &updateState);
3664             nvPopEvoSubDevMask(pDevEvo);
3665             kickOff = TRUE;
3666         }
3667     }
3668 
3669     if (kickOff) {
3670         EvoUpdate91(pDevEvo, &updateState, TRUE /* releaseElv */);
3671     }
3672 }
3673 
EvoComputeWindowScalingTaps91(const NVDevEvoRec * pDevEvo,const NVEvoChannel * pChannel,NVFlipChannelEvoHwState * pHwState)3674 static NvBool EvoComputeWindowScalingTaps91(const NVDevEvoRec *pDevEvo,
3675                                             const NVEvoChannel *pChannel,
3676                                             NVFlipChannelEvoHwState *pHwState)
3677 {
3678     /* Window scaling isn't supported on EVO. */
3679     if ((pHwState->sizeIn.width != pHwState->sizeOut.width) ||
3680         (pHwState->sizeIn.height != pHwState->sizeOut.height))
3681     {
3682         return FALSE;
3683     }
3684 
3685     pHwState->hTaps = NV_EVO_SCALER_1TAP;
3686     pHwState->vTaps = NV_EVO_SCALER_1TAP;
3687 
3688     return TRUE;
3689 }
3690 
GetAccelerators(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NvU32 sd)3691 static NvU32 GetAccelerators(
3692     NVDevEvoPtr pDevEvo,
3693     NVEvoChannelPtr pChannel,
3694     NvU32 sd)
3695 {
3696     NV5070_CTRL_GET_ACCL_PARAMS params = { };
3697     NvU32 ret;
3698 
3699     params.base.subdeviceIndex = sd;
3700     params.channelClass = pChannel->hwclass;
3701     nvAssert(pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL);
3702     params.channelInstance = pChannel->instance;
3703 
3704     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
3705                          pDevEvo->displayHandle,
3706                          NV5070_CTRL_CMD_GET_ACCL,
3707                          &params, sizeof(params));
3708     if (ret != NVOS_STATUS_SUCCESS) {
3709         nvEvoLogDevDebug(pDevEvo, EVO_LOG_ERROR,
3710                          "Failed to retrieve accelerators");
3711         return 0;
3712     }
3713 
3714     return params.accelerators;
3715 }
3716 
SetAccelerators(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NvU32 sd,NvU32 accelerators,NvU32 accelMask)3717 static NvBool SetAccelerators(
3718     NVDevEvoPtr pDevEvo,
3719     NVEvoChannelPtr pChannel,
3720     NvU32 sd,
3721     NvU32 accelerators,
3722     NvU32 accelMask)
3723 {
3724     NV5070_CTRL_SET_ACCL_PARAMS params = { };
3725     NvU32 ret;
3726 
3727     params.base.subdeviceIndex = sd;
3728     params.channelClass = pChannel->hwclass;
3729     nvAssert(pChannel->channelMask & NV_EVO_CHANNEL_MASK_BASE_ALL);
3730     params.channelInstance = pChannel->instance;
3731     params.accelerators = accelerators;
3732     params.accelMask = accelMask;
3733 
3734     ret = nvRmApiControl(nvEvoGlobal.clientHandle,
3735                          pDevEvo->displayHandle,
3736                          NV5070_CTRL_CMD_SET_ACCL,
3737                          &params, sizeof(params));
3738     if (ret != NVOS_STATUS_SUCCESS) {
3739         nvEvoLogDevDebug(pDevEvo, EVO_LOG_ERROR,
3740                          "Failed to set accelerators");
3741         return FALSE;
3742     }
3743 
3744     return TRUE;
3745 }
3746 
EvoAccelerateChannel91(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,const NvU32 sd,const NvBool trashPendingMethods,const NvBool unblockMethodsInExecutation,NvU32 * pOldAccelerators)3747 static void EvoAccelerateChannel91(NVDevEvoPtr pDevEvo,
3748                                    NVEvoChannelPtr pChannel,
3749                                    const NvU32 sd,
3750                                    const NvBool trashPendingMethods,
3751                                    const NvBool unblockMethodsInExecutation,
3752                                    NvU32 *pOldAccelerators)
3753 {
3754     NvU32 accelMask = 0x0;
3755 
3756     if (trashPendingMethods) {
3757         accelMask |= NV5070_CTRL_ACCL_TRASH_ONLY;
3758     }
3759 
3760     /* Start with a conservative set of accelerators; may need to add more
3761      * later. */
3762     if (unblockMethodsInExecutation) {
3763         accelMask |= NV5070_CTRL_ACCL_IGNORE_PI |
3764                      NV5070_CTRL_ACCL_SKIP_SEMA |
3765                      NV5070_CTRL_ACCL_IGNORE_FLIPLOCK;
3766     }
3767 
3768     if (accelMask == 0x0) {
3769         return;
3770     }
3771 
3772     *pOldAccelerators = GetAccelerators(pDevEvo, pChannel, sd);
3773 
3774     /* Accelerate window channel. */
3775     if (!SetAccelerators(pDevEvo, pChannel, sd, accelMask, accelMask)) {
3776         nvAssert(!"Failed to set accelerators");
3777     }
3778 }
3779 
EvoResetChannelAccelerators91(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,const NvU32 sd,const NvBool trashPendingMethods,const NvBool unblockMethodsInExecutation,NvU32 oldAccelerators)3780 static void EvoResetChannelAccelerators91(NVDevEvoPtr pDevEvo,
3781                                           NVEvoChannelPtr pChannel,
3782                                           const NvU32 sd,
3783                                           const NvBool trashPendingMethods,
3784                                           const NvBool unblockMethodsInExecutation,
3785                                           NvU32 oldAccelerators)
3786 {
3787     NvU32 accelMask = 0x0;
3788 
3789     if (trashPendingMethods) {
3790         accelMask |= NV5070_CTRL_ACCL_TRASH_ONLY;
3791     }
3792 
3793     /* Start with a conservative set of accelerators; may need to add more
3794      * later. */
3795     if (unblockMethodsInExecutation) {
3796         accelMask |= NV5070_CTRL_ACCL_IGNORE_PI |
3797                      NV5070_CTRL_ACCL_SKIP_SEMA |
3798                      NV5070_CTRL_ACCL_IGNORE_FLIPLOCK;
3799     }
3800 
3801     if (accelMask == 0x0) {
3802         return;
3803     }
3804 
3805     /* Accelerate window channel. */
3806     if (!SetAccelerators(pDevEvo, pChannel, sd, oldAccelerators, accelMask)) {
3807         nvAssert(!"Failed to set accelerators");
3808     }
3809 }
3810 
EvoAllocSurfaceDescriptor90(NVDevEvoPtr pDevEvo,NVSurfaceDescriptor * pSurfaceDesc,NvU32 memoryHandle,NvU32 localCtxDmaFlags,NvU64 limit)3811 static NvU32 EvoAllocSurfaceDescriptor90(
3812     NVDevEvoPtr pDevEvo, NVSurfaceDescriptor *pSurfaceDesc,
3813     NvU32 memoryHandle, NvU32 localCtxDmaFlags,
3814     NvU64 limit)
3815 {
3816     return nvCtxDmaAlloc(pDevEvo, &pSurfaceDesc->ctxDmaHandle,
3817                          memoryHandle,
3818                          localCtxDmaFlags, limit);
3819 }
3820 
EvoFreeSurfaceDescriptor90(NVDevEvoPtr pDevEvo,NvU32 deviceHandle,NVSurfaceDescriptor * pSurfaceDesc)3821 static void EvoFreeSurfaceDescriptor90(
3822     NVDevEvoPtr pDevEvo,
3823     NvU32 deviceHandle,
3824     NVSurfaceDescriptor *pSurfaceDesc)
3825 {
3826     nvCtxDmaFree(pDevEvo, deviceHandle, &pSurfaceDesc->ctxDmaHandle);
3827 }
3828 
EvoBindSurfaceDescriptor90(NVDevEvoPtr pDevEvo,NVEvoChannelPtr pChannel,NVSurfaceDescriptor * pSurfaceDesc)3829 static NvU32 EvoBindSurfaceDescriptor90(
3830     NVDevEvoPtr pDevEvo, NVEvoChannelPtr pChannel, NVSurfaceDescriptor *pSurfaceDesc)
3831 {
3832     return nvCtxDmaBind(pDevEvo, pChannel, pSurfaceDesc->ctxDmaHandle);
3833 }
3834 
3835 NVEvoHAL nvEvo94 = {
3836     EvoSetRasterParams91,                         /* SetRasterParams */
3837     EvoSetProcAmp90,                              /* SetProcAmp */
3838     EvoSetHeadControl90,                          /* SetHeadControl */
3839     EvoSetHeadRefClk90,                           /* SetHeadRefClk */
3840     EvoHeadSetControlOR90,                        /* HeadSetControlOR */
3841     EvoORSetControl90,                            /* ORSetControl */
3842     EvoHeadSetDisplayId90,                        /* HeadSetDisplayId */
3843     EvoSetUsageBounds90,                          /* SetUsageBounds */
3844     EvoUpdate91,                                  /* Update */
3845     nvEvo1IsModePossible,                         /* IsModePossible */
3846     nvEvo1PrePostIMP,                             /* PrePostIMP */
3847     EvoSetNotifier90,                             /* SetNotifier */
3848     EvoGetCapabilities90,                         /* GetCapabilities */
3849     EvoFlip90,                                    /* Flip */
3850     EvoFlipTransitionWAR90,                       /* FlipTransitionWAR */
3851     EvoFillLUTSurface90,                          /* FillLUTSurface */
3852     EvoSetLUTContextDma90,                        /* SetLUTContextDma */
3853     EvoSetOutputScaler90,                         /* SetOutputScaler */
3854     EvoSetViewportPointIn90,                      /* SetViewportPointIn */
3855     EvoSetViewportInOut90,                        /* SetViewportInOut */
3856     EvoSetCursorImage91,                          /* SetCursorImage */
3857     EvoValidateCursorSurface90,                   /* ValidateCursorSurface */
3858     EvoValidateWindowFormat90,                    /* ValidateWindowFormat */
3859     EvoInitCompNotifier3,                         /* InitCompNotifier */
3860     EvoIsCompNotifierComplete3,                   /* IsCompNotifierComplete */
3861     EvoWaitForCompNotifier3,                      /* WaitForCompNotifier */
3862     EvoSetDither91,                               /* SetDither */
3863     EvoSetStallLock94,                            /* SetStallLock */
3864     NULL,                                         /* SetDisplayRate */
3865     EvoInitChannel90,                             /* InitChannel */
3866     NULL,                                         /* InitDefaultLut */
3867     EvoInitWindowMapping90,                       /* InitWindowMapping */
3868     nvEvo1IsChannelIdle,                          /* IsChannelIdle */
3869     nvEvo1IsChannelMethodPending,                 /* IsChannelMethodPending */
3870     EvoForceIdleSatelliteChannel90,               /* ForceIdleSatelliteChannel */
3871     EvoForceIdleSatelliteChannel90,               /* ForceIdleSatelliteChannelIgnoreLock */
3872     EvoAccelerateChannel91,                       /* AccelerateChannel */
3873     EvoResetChannelAccelerators91,                /* ResetChannelAccelerators */
3874     EvoAllocRmCtrlObject90,                       /* AllocRmCtrlObject */
3875     EvoFreeRmCtrlObject90,                        /* FreeRmCtrlObject */
3876     EvoSetImmPointOut91,                          /* SetImmPointOut */
3877     EvoStartHeadCRC32Capture90,                   /* StartCRC32Capture */
3878     EvoStopHeadCRC32Capture90,                    /* StopCRC32Capture */
3879     EvoQueryHeadCRC32_90,                         /* QueryCRC32 */
3880     EvoGetScanLine90,                             /* GetScanLine */
3881     NULL,                                         /* ConfigureVblankSyncObject */
3882     nvEvo1SetDscParams,                           /* SetDscParams */
3883     NULL,                                         /* EnableMidFrameAndDWCFWatermark */
3884     EvoGetActiveViewportOffset94,                 /* GetActiveViewportOffset */
3885     EvoClearSurfaceUsage91,                       /* ClearSurfaceUsage */
3886     EvoComputeWindowScalingTaps91,                /* ComputeWindowScalingTaps */
3887     NULL,                                         /* GetWindowScalingCaps */
3888     NULL,                                         /* SetMergeMode */
3889     EvoAllocSurfaceDescriptor90,                  /* AllocSurfaceDescriptor */
3890     EvoFreeSurfaceDescriptor90,                   /* FreeSurfaceDescriptor */
3891     EvoBindSurfaceDescriptor90,                   /* BindSurfaceDescriptor */
3892     NULL,                                         /* SetTmoLutSurfaceAddress */
3893     NULL,                                         /* SetILUTSurfaceAddress */
3894     NULL,                                         /* SetISOSurfaceAddress */
3895     NULL,                                         /* SetCoreNotifierSurfaceAddressAndControl */
3896     NULL,                                         /* SetWinNotifierSurfaceAddressAndControl */
3897     NULL,                                         /* SetSemaphoreSurfaceAddressAndControl */
3898     NULL,                                         /* SetAcqSemaphoreSurfaceAddressAndControl */
3899     {                                             /* caps */
3900         FALSE,                                    /* supportsNonInterlockedUsageBoundsUpdate */
3901         FALSE,                                    /* supportsDisplayRate */
3902         TRUE,                                     /* supportsFlipLockRGStatus */
3903         FALSE,                                    /* needDefaultLutSurface */
3904         FALSE,                                    /* hasUnorm10OLUT */
3905         TRUE,                                     /* supportsImageSharpening */
3906         FALSE,                                    /* supportsHDMIVRR */
3907         TRUE,                                     /* supportsCoreChannelSurface */
3908         FALSE,                                    /* supportsHDMIFRL */
3909         TRUE,                                     /* supportsSetStorageMemoryLayout */
3910         FALSE,                                    /* supportsIndependentAcqRelSemaphore */
3911         TRUE,                                     /* supportsCoreLut */
3912         FALSE,                                    /* supportsSynchronizedOverlayPositionUpdate */
3913         FALSE,                                    /* supportsVblankSyncObjects */
3914         TRUE,                                     /* requiresScalingTapsInBothDimensions */
3915         FALSE,                                    /* supportsMergeMode */
3916         FALSE,                                    /* supportsHDMI10BPC */
3917         NV_EVO2_SUPPORTED_DITHERING_MODES,        /* supportedDitheringModes */
3918         sizeof(NV5070_CTRL_CMD_IS_MODE_POSSIBLE_PARAMS), /* impStructSize */
3919         NV_EVO_SCALER_1TAP,                       /* minScalerTaps */
3920         0,                                        /* xEmulatedSurfaceMemoryFormats */
3921     },
3922 };
3923