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 ¶ms, 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 ¶ms, 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 ¶ms, 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