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