1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2010-2014 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 /*
24 * This header file defines the types NVDpyId and NVDpyIdList, as well
25 * as inline functions to manipulate these types. NVDpyId and
26 * NVDpyIdList should be treated as opaque by includers of this header
27 * file.
28 */
29
30 #ifndef __NV_DPY_ID_H__
31 #define __NV_DPY_ID_H__
32
33 #include "nvtypes.h"
34 #include "nvmisc.h"
35 #include "nv_common_utils.h"
36 #include <nvlimits.h> /* NV_MAX_SUBDEVICES */
37
38 typedef struct {
39 NvU32 opaqueDpyId;
40 } NVDpyId;
41
42 typedef struct {
43 NvU32 opaqueDpyIdList;
44 } NVDpyIdList;
45
46 #define NV_DPY_ID_MAX_SUBDEVICES NV_MAX_SUBDEVICES
47 #define NV_DPY_ID_MAX_DPYS_IN_LIST 32
48
49 /*
50 * For use in combination with nvDpyIdToPrintFormat(); e.g.,
51 *
52 * printf("dpy id: " NV_DPY_ID_PRINT_FORMAT "\n",
53 * nvDpyIdToPrintFormat(dpyId));
54 *
55 * The includer should not make assumptions about the return type of
56 * nvDpyIdToPrintFormat().
57 */
58 #define NV_DPY_ID_PRINT_FORMAT "0x%08x"
59
60 /* functions to return an invalid DpyId and empty DpyIdList */
61
nvInvalidDpyId(void)62 static inline NVDpyId nvInvalidDpyId(void)
63 {
64 NVDpyId dpyId = { 0 };
65 return dpyId;
66 }
67
nvEmptyDpyIdList(void)68 static inline NVDpyIdList nvEmptyDpyIdList(void)
69 {
70 NVDpyIdList dpyIdList = { 0 };
71 return dpyIdList;
72 }
73
nvAllDpyIdList(void)74 static inline NVDpyIdList nvAllDpyIdList(void)
75 {
76 NVDpyIdList dpyIdList = { ~0U };
77 return dpyIdList;
78 }
79
80 static inline void
nvEmptyDpyIdListSubDeviceArray(NVDpyIdList dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])81 nvEmptyDpyIdListSubDeviceArray(NVDpyIdList dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
82 {
83 int dispIndex;
84 for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
85 dpyIdList[dispIndex] = nvEmptyDpyIdList();
86 }
87 }
88
89 /* set operations on DpyIds and DpyIdLists: Add, Subtract, Intersect, Xor */
90
91 static inline __attribute__ ((warn_unused_result))
nvAddDpyIdToDpyIdList(NVDpyId dpyId,NVDpyIdList dpyIdList)92 NVDpyIdList nvAddDpyIdToDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
93 {
94 NVDpyIdList tmpDpyIdList;
95 tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList |
96 dpyId.opaqueDpyId;
97 return tmpDpyIdList;
98 }
99
100 /* Passing an invalid display ID makes this function return an empty list. */
101 static inline __attribute__ ((warn_unused_result))
nvAddDpyIdToEmptyDpyIdList(NVDpyId dpyId)102 NVDpyIdList nvAddDpyIdToEmptyDpyIdList(NVDpyId dpyId)
103 {
104 NVDpyIdList tmpDpyIdList;
105 tmpDpyIdList.opaqueDpyIdList = dpyId.opaqueDpyId;
106 return tmpDpyIdList;
107 }
108
109 static inline __attribute__ ((warn_unused_result))
nvAddDpyIdListToDpyIdList(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)110 NVDpyIdList nvAddDpyIdListToDpyIdList(NVDpyIdList dpyIdListA,
111 NVDpyIdList dpyIdListB)
112 {
113 NVDpyIdList tmpDpyIdList;
114 tmpDpyIdList.opaqueDpyIdList = dpyIdListB.opaqueDpyIdList |
115 dpyIdListA.opaqueDpyIdList;
116 return tmpDpyIdList;
117 }
118
119 /* Returns: dpyIdList - dpyId */
120 static inline __attribute__ ((warn_unused_result))
nvDpyIdListMinusDpyId(NVDpyIdList dpyIdList,NVDpyId dpyId)121 NVDpyIdList nvDpyIdListMinusDpyId(NVDpyIdList dpyIdList, NVDpyId dpyId)
122 {
123 NVDpyIdList tmpDpyIdList;
124 tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList &
125 (~dpyId.opaqueDpyId);
126 return tmpDpyIdList;
127 }
128
129 /* Returns: dpyIdListA - dpyIdListB */
130 static inline __attribute__ ((warn_unused_result))
nvDpyIdListMinusDpyIdList(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)131 NVDpyIdList nvDpyIdListMinusDpyIdList(NVDpyIdList dpyIdListA,
132 NVDpyIdList dpyIdListB)
133 {
134 NVDpyIdList tmpDpyIdList;
135 tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList &
136 (~dpyIdListB.opaqueDpyIdList);
137 return tmpDpyIdList;
138 }
139
140 static inline __attribute__ ((warn_unused_result))
nvIntersectDpyIdAndDpyIdList(NVDpyId dpyId,NVDpyIdList dpyIdList)141 NVDpyIdList nvIntersectDpyIdAndDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
142 {
143 NVDpyIdList tmpDpyIdList;
144 tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList &
145 dpyId.opaqueDpyId;
146 return tmpDpyIdList;
147 }
148
149 static inline __attribute__ ((warn_unused_result))
nvIntersectDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)150 NVDpyIdList nvIntersectDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,
151 NVDpyIdList dpyIdListB)
152 {
153 NVDpyIdList tmpDpyIdList;
154 tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList &
155 dpyIdListB.opaqueDpyIdList;
156 return tmpDpyIdList;
157 }
158
159 static inline __attribute__ ((warn_unused_result))
nvXorDpyIdAndDpyIdList(NVDpyId dpyId,NVDpyIdList dpyIdList)160 NVDpyIdList nvXorDpyIdAndDpyIdList(NVDpyId dpyId, NVDpyIdList dpyIdList)
161 {
162 NVDpyIdList tmpDpyIdList;
163 tmpDpyIdList.opaqueDpyIdList = dpyIdList.opaqueDpyIdList ^
164 dpyId.opaqueDpyId;
165 return tmpDpyIdList;
166 }
167
168 static inline __attribute__ ((warn_unused_result))
nvXorDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)169 NVDpyIdList nvXorDpyIdListAndDpyIdList(NVDpyIdList dpyIdListA,
170 NVDpyIdList dpyIdListB)
171 {
172 NVDpyIdList tmpDpyIdList;
173 tmpDpyIdList.opaqueDpyIdList = dpyIdListA.opaqueDpyIdList ^
174 dpyIdListB.opaqueDpyIdList;
175 return tmpDpyIdList;
176 }
177
178
179 /* boolean checks */
180
nvDpyIdIsInDpyIdList(NVDpyId dpyId,NVDpyIdList dpyIdList)181 static inline NvBool nvDpyIdIsInDpyIdList(NVDpyId dpyId,
182 NVDpyIdList dpyIdList)
183 {
184 return !!(dpyIdList.opaqueDpyIdList & dpyId.opaqueDpyId);
185 }
186
nvDpyIdIsInvalid(NVDpyId dpyId)187 static inline NvBool nvDpyIdIsInvalid(NVDpyId dpyId)
188 {
189 return (dpyId.opaqueDpyId == 0);
190 }
191
nvDpyIdListIsEmpty(NVDpyIdList dpyIdList)192 static inline NvBool nvDpyIdListIsEmpty(NVDpyIdList dpyIdList)
193 {
194 return (dpyIdList.opaqueDpyIdList == 0);
195 }
196
197 static inline NvBool
nvDpyIdListSubDeviceArrayIsEmpty(NVDpyIdList dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])198 nvDpyIdListSubDeviceArrayIsEmpty(NVDpyIdList
199 dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
200 {
201 int dispIndex;
202 for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
203 if (!nvDpyIdListIsEmpty(dpyIdList[dispIndex])) {
204 return NV_FALSE;
205 }
206 }
207 return NV_TRUE;
208 }
209
210
nvDpyIdsAreEqual(NVDpyId dpyIdA,NVDpyId dpyIdB)211 static inline NvBool nvDpyIdsAreEqual(NVDpyId dpyIdA, NVDpyId dpyIdB)
212 {
213 return (dpyIdA.opaqueDpyId == dpyIdB.opaqueDpyId);
214 }
215
nvDpyIdListsAreEqual(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)216 static inline NvBool nvDpyIdListsAreEqual(NVDpyIdList dpyIdListA,
217 NVDpyIdList dpyIdListB)
218 {
219 return (dpyIdListA.opaqueDpyIdList == dpyIdListB.opaqueDpyIdList);
220 }
221
nvDpyIdListIsASubSetofDpyIdList(NVDpyIdList dpyIdListA,NVDpyIdList dpyIdListB)222 static inline NvBool nvDpyIdListIsASubSetofDpyIdList(NVDpyIdList dpyIdListA,
223 NVDpyIdList dpyIdListB)
224 {
225 NVDpyIdList intersectedDpyIdList =
226 nvIntersectDpyIdListAndDpyIdList(dpyIdListA, dpyIdListB);
227
228 return nvDpyIdListsAreEqual(intersectedDpyIdList, dpyIdListA);
229 }
230
231
232 /*
233 * retrieve the individual dpyIds from dpyIdList; if dpyId is invalid,
234 * start at the beginning of the list; otherwise, start at the dpyId
235 * after the specified dpyId
236 */
237
238 static inline __attribute__ ((warn_unused_result))
nvNextDpyIdInDpyIdListUnsorted(NVDpyId dpyId,NVDpyIdList dpyIdList)239 NVDpyId nvNextDpyIdInDpyIdListUnsorted(NVDpyId dpyId, NVDpyIdList dpyIdList)
240 {
241 if (nvDpyIdIsInvalid(dpyId)) {
242 dpyId.opaqueDpyId = 1;
243 } else {
244 dpyId.opaqueDpyId <<= 1;
245 }
246
247 while (dpyId.opaqueDpyId) {
248
249 if (nvDpyIdIsInDpyIdList(dpyId, dpyIdList)) {
250 return dpyId;
251 }
252
253 dpyId.opaqueDpyId <<= 1;
254 }
255
256 /* no dpyIds left in dpyIdlist; return the invalid dpyId */
257
258 return nvInvalidDpyId();
259 }
260
261 #define FOR_ALL_DPY_IDS(_dpyId, _dpyIdList) \
262 for ((_dpyId) = nvNextDpyIdInDpyIdListUnsorted(nvInvalidDpyId(), \
263 (_dpyIdList)); \
264 !nvDpyIdIsInvalid(_dpyId); \
265 (_dpyId) = nvNextDpyIdInDpyIdListUnsorted((_dpyId), \
266 (_dpyIdList)))
267
268 /* report how many dpyIds are in the dpyIdList */
269
nvCountDpyIdsInDpyIdList(NVDpyIdList dpyIdList)270 static inline int nvCountDpyIdsInDpyIdList(NVDpyIdList dpyIdList)
271 {
272 return nvPopCount32(dpyIdList.opaqueDpyIdList);
273 }
274
275 static inline int
nvCountDpyIdsInDpyIdListSubDeviceArray(NVDpyIdList dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])276 nvCountDpyIdsInDpyIdListSubDeviceArray(NVDpyIdList
277 dpyIdList[NV_DPY_ID_MAX_SUBDEVICES])
278 {
279 int dispIndex, n = 0;
280
281 for (dispIndex = 0; dispIndex < NV_DPY_ID_MAX_SUBDEVICES; dispIndex++) {
282 n += nvCountDpyIdsInDpyIdList(dpyIdList[dispIndex]);
283 }
284
285 return n;
286 }
287
288 /* convert between dpyId/dpyIdList and NV-CONTROL values */
289
nvDpyIdToNvControlVal(NVDpyId dpyId)290 static inline int nvDpyIdToNvControlVal(NVDpyId dpyId)
291 {
292 return (int) dpyId.opaqueDpyId;
293 }
294
nvDpyIdListToNvControlVal(NVDpyIdList dpyIdList)295 static inline int nvDpyIdListToNvControlVal(NVDpyIdList dpyIdList)
296 {
297 return (int) dpyIdList.opaqueDpyIdList;
298 }
299
nvNvControlValToDpyId(int val)300 static inline NVDpyId nvNvControlValToDpyId(int val)
301 {
302 NVDpyId dpyId;
303 dpyId.opaqueDpyId = (val == 0) ? 0 : 1 << (nv_ffs(val)-1);
304 return dpyId;
305 }
306
nvNvControlValToDpyIdList(int val)307 static inline NVDpyIdList nvNvControlValToDpyIdList(int val)
308 {
309 NVDpyIdList dpyIdList;
310 dpyIdList.opaqueDpyIdList = val;
311 return dpyIdList;
312 }
313
314
315 /* convert between dpyId and NvU32 */
316
nvNvU32ToDpyId(NvU32 val)317 static inline NVDpyId nvNvU32ToDpyId(NvU32 val)
318 {
319 NVDpyId dpyId;
320 dpyId.opaqueDpyId = (val == 0) ? 0 : 1 << (nv_ffs(val)-1);
321 return dpyId;
322 }
323
nvNvU32ToDpyIdList(NvU32 val)324 static inline NVDpyIdList nvNvU32ToDpyIdList(NvU32 val)
325 {
326 NVDpyIdList dpyIdList;
327 dpyIdList.opaqueDpyIdList = val;
328 return dpyIdList;
329 }
330
nvDpyIdToNvU32(NVDpyId dpyId)331 static inline NvU32 nvDpyIdToNvU32(NVDpyId dpyId)
332 {
333 return dpyId.opaqueDpyId;
334 }
335
nvDpyIdListToNvU32(NVDpyIdList dpyIdList)336 static inline NvU32 nvDpyIdListToNvU32(NVDpyIdList dpyIdList)
337 {
338 return dpyIdList.opaqueDpyIdList;
339 }
340
341 /* Return the bit position of dpyId: a number in the range [0..31]. */
nvDpyIdToIndex(NVDpyId dpyId)342 static inline NvU32 nvDpyIdToIndex(NVDpyId dpyId)
343 {
344 return nv_ffs(dpyId.opaqueDpyId) - 1;
345 }
346
347 /* Return a display ID that is not in the list passed in. */
348
nvNewDpyId(NVDpyIdList excludeList)349 static inline NVDpyId nvNewDpyId(NVDpyIdList excludeList)
350 {
351 NVDpyId dpyId;
352 if (~excludeList.opaqueDpyIdList == 0) {
353 return nvInvalidDpyId();
354 }
355 dpyId.opaqueDpyId =
356 1U << (nv_ffs(~excludeList.opaqueDpyIdList) - 1);
357 return dpyId;
358 }
359
360 /* See comment for NV_DPY_ID_PRINT_FORMAT. */
nvDpyIdToPrintFormat(NVDpyId dpyId)361 static inline NvU32 nvDpyIdToPrintFormat(NVDpyId dpyId)
362 {
363 return nvDpyIdToNvU32(dpyId);
364 }
365
366 /* Prevent usage of opaque values. */
367 #define opaqueDpyId __ERROR_ACCESS_ME_VIA_NV_DPY_ID_H
368 #define opaqueDpyIdList __ERROR_ACCESS_ME_VIA_NV_DPY_ID_H
369
370 #endif /* __NV_DPY_ID_H__ */
371