1 /*
2  * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #ifndef __NVIDIA_DRM_HELPER_H__
24 #define __NVIDIA_DRM_HELPER_H__
25 
26 #include "nvidia-drm-conftest.h"
27 
28 #if defined(NV_DRM_AVAILABLE)
29 
30 #if defined(NV_DRM_DRMP_H_PRESENT)
31 #include <drm/drmP.h>
32 #endif
33 
34 #if defined(NV_DRM_DRM_DRV_H_PRESENT)
35 #include <drm/drm_drv.h>
36 #endif
37 
38 #if defined(NV_DRM_ALPHA_BLENDING_AVAILABLE) || defined(NV_DRM_ROTATION_AVAILABLE)
39 /* For DRM_ROTATE_* , DRM_REFLECT_* */
40 #include <drm/drm_blend.h>
41 #endif
42 
43 #if defined(NV_DRM_ROTATION_AVAILABLE)
44 /* For DRM_MODE_ROTATE_* and DRM_MODE_REFLECT_* */
45 #include <uapi/drm/drm_mode.h>
46 #endif
47 
48 #if defined(NV_DRM_ROTATION_AVAILABLE)
49 /*
50  * 19-05-2017 c2c446ad29437bb92b157423c632286608ebd3ec has added
51  * DRM_MODE_ROTATE_* and DRM_MODE_REFLECT_* to UAPI and removed
52  * DRM_ROTATE_* and DRM_REFLECT_*
53  */
54 #if !defined(DRM_MODE_ROTATE_0)
55 #define DRM_MODE_ROTATE_0       DRM_ROTATE_0
56 #define DRM_MODE_ROTATE_90      DRM_ROTATE_90
57 #define DRM_MODE_ROTATE_180     DRM_ROTATE_180
58 #define DRM_MODE_ROTATE_270     DRM_ROTATE_270
59 #define DRM_MODE_REFLECT_X      DRM_REFLECT_X
60 #define DRM_MODE_REFLECT_Y      DRM_REFLECT_Y
61 #define DRM_MODE_ROTATE_MASK    DRM_ROTATE_MASK
62 #define DRM_MODE_REFLECT_MASK   DRM_REFLECT_MASK
63 #endif
64 
65 #endif //NV_DRM_ROTATION_AVAILABLE
66 
67 /*
68  * drm_dev_put() is added by commit 9a96f55034e41b4e002b767e9218d55f03bdff7d
69  * (2017-09-26) and drm_dev_unref() is removed by
70  * ba1d345401476a5f7fbad622607c5a1f95e59b31 (2018-11-15).
71  *
72  * drm_dev_unref() has been added and drm_dev_free() removed by commit -
73  *
74  *      2014-01-29: 099d1c290e2ebc3b798961a6c177c3aef5f0b789
75  */
76 static inline void nv_drm_dev_free(struct drm_device *dev)
77 {
78 #if defined(NV_DRM_DEV_PUT_PRESENT)
79     drm_dev_put(dev);
80 #elif defined(NV_DRM_DEV_UNREF_PRESENT)
81     drm_dev_unref(dev);
82 #else
83     drm_dev_free(dev);
84 #endif
85 }
86 
87 #if defined(NV_DRM_DRM_PRIME_H_PRESENT)
88 #include <drm/drm_prime.h>
89 #endif
90 
91 static inline struct sg_table*
92 nv_drm_prime_pages_to_sg(struct drm_device *dev,
93                          struct page **pages, unsigned int nr_pages)
94 {
95 #if defined(NV_DRM_PRIME_PAGES_TO_SG_HAS_DRM_DEVICE_ARG)
96     return drm_prime_pages_to_sg(dev, pages, nr_pages);
97 #else
98     return drm_prime_pages_to_sg(pages, nr_pages);
99 #endif
100 }
101 
102 #if defined(NV_DRM_ATOMIC_MODESET_AVAILABLE)
103 
104 /*
105  * drm_for_each_connector(), drm_for_each_crtc(), drm_for_each_fb(),
106  * drm_for_each_encoder and drm_for_each_plane() were added by kernel
107  * commit 6295d607ad34ee4e43aab3f20714c2ef7a6adea1 which was
108  * Signed-off-by:
109  *     Daniel Vetter <daniel.vetter@intel.com>
110  * drm_for_each_connector(), drm_for_each_crtc(), drm_for_each_fb(),
111  * drm_for_each_encoder and drm_for_each_plane() are copied from
112  *      include/drm/drm_crtc @
113  *      6295d607ad34ee4e43aab3f20714c2ef7a6adea1
114  * which has the following copyright and license information:
115  *
116  * Copyright © 2006 Keith Packard
117  * Copyright © 2007-2008 Dave Airlie
118  * Copyright © 2007-2008 Intel Corporation
119  *   Jesse Barnes <jesse.barnes@intel.com>
120  *
121  * Permission is hereby granted, free of charge, to any person obtaining a
122  * copy of this software and associated documentation files (the "Software"),
123  * to deal in the Software without restriction, including without limitation
124  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
125  * and/or sell copies of the Software, and to permit persons to whom the
126  * Software is furnished to do so, subject to the following conditions:
127  *
128  * The above copyright notice and this permission notice shall be included in
129  * all copies or substantial portions of the Software.
130  *
131  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
132  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
133  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
134  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
135  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
136  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
137  * OTHER DEALINGS IN THE SOFTWARE.
138  */
139 #include <drm/drm_crtc.h>
140 
141 #if defined(drm_for_each_plane)
142 #define nv_drm_for_each_plane(plane, dev) \
143     drm_for_each_plane(plane, dev)
144 #else
145 #define nv_drm_for_each_plane(plane, dev) \
146     list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
147 #endif
148 
149 #if defined(drm_for_each_crtc)
150 #define nv_drm_for_each_crtc(crtc, dev) \
151     drm_for_each_crtc(crtc, dev)
152 #else
153 #define nv_drm_for_each_crtc(crtc, dev) \
154     list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
155 #endif
156 
157 #if defined(NV_DRM_CONNECTOR_LIST_ITER_PRESENT)
158 #define nv_drm_for_each_connector(connector, conn_iter, dev) \
159         drm_for_each_connector_iter(connector, conn_iter)
160 #elif defined(drm_for_each_connector)
161 #define nv_drm_for_each_connector(connector, conn_iter, dev) \
162     drm_for_each_connector(connector, dev)
163 #else
164 #define nv_drm_for_each_connector(connector, conn_iter, dev) \
165     WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));      \
166     list_for_each_entry(connector, &(dev)->mode_config.connector_list, head)
167 #endif
168 
169 #if defined(drm_for_each_encoder)
170 #define nv_drm_for_each_encoder(encoder, dev) \
171     drm_for_each_encoder(encoder, dev)
172 #else
173 #define nv_drm_for_each_encoder(encoder, dev) \
174     list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head)
175 #endif
176 
177 #if defined(drm_for_each_fb)
178 #define nv_drm_for_each_fb(fb, dev) \
179     drm_for_each_fb(fb, dev)
180 #else
181 #define nv_drm_for_each_fb(fb, dev) \
182     list_for_each_entry(fb, &(dev)->mode_config.fb_list, head)
183 #endif
184 
185 #include <drm/drm_atomic.h>
186 #include <drm/drm_atomic_helper.h>
187 
188 int nv_drm_atomic_helper_disable_all(struct drm_device *dev,
189                                      struct drm_modeset_acquire_ctx *ctx);
190 
191 /*
192  * for_each_connector_in_state(), for_each_crtc_in_state() and
193  * for_each_plane_in_state() were added by kernel commit
194  * df63b9994eaf942afcdb946d27a28661d7dfbf2a which was Signed-off-by:
195  *      Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
196  *      Daniel Vetter <daniel.vetter@ffwll.ch>
197  *
198  * for_each_connector_in_state(), for_each_crtc_in_state() and
199  * for_each_plane_in_state() were copied from
200  *      include/drm/drm_atomic.h @
201  *      21a01abbe32a3cbeb903378a24e504bfd9fe0648
202  * which has the following copyright and license information:
203  *
204  * Copyright (C) 2014 Red Hat
205  * Copyright (C) 2014 Intel Corp.
206  *
207  * Permission is hereby granted, free of charge, to any person obtaining a
208  * copy of this software and associated documentation files (the "Software"),
209  * to deal in the Software without restriction, including without limitation
210  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
211  * and/or sell copies of the Software, and to permit persons to whom the
212  * Software is furnished to do so, subject to the following conditions:
213  *
214  * The above copyright notice and this permission notice shall be included in
215  * all copies or substantial portions of the Software.
216  *
217  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
218  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
219  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
220  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
221  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
222  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
223  * OTHER DEALINGS IN THE SOFTWARE.
224  *
225  * Authors:
226  * Rob Clark <robdclark@gmail.com>
227  * Daniel Vetter <daniel.vetter@ffwll.ch>
228  */
229 
230 /**
231  * nv_drm_for_each_connector_in_state - iterate over all connectors in an
232  * atomic update
233  * @__state: &struct drm_atomic_state pointer
234  * @connector: &struct drm_connector iteration cursor
235  * @connector_state: &struct drm_connector_state iteration cursor
236  * @__i: int iteration cursor, for macro-internal use
237  *
238  * This iterates over all connectors in an atomic update. Note that before the
239  * software state is committed (by calling drm_atomic_helper_swap_state(), this
240  * points to the new state, while afterwards it points to the old state. Due to
241  * this tricky confusion this macro is deprecated.
242  */
243 #if !defined(for_each_connector_in_state)
244 #define nv_drm_for_each_connector_in_state(__state,                         \
245                                            connector, connector_state, __i) \
246        for ((__i) = 0;                                                      \
247             (__i) < (__state)->num_connector &&                             \
248             ((connector) = (__state)->connectors[__i].ptr,                  \
249             (connector_state) = (__state)->connectors[__i].state, 1);       \
250             (__i)++)                                                        \
251                for_each_if (connector)
252 #else
253 #define nv_drm_for_each_connector_in_state(__state,                         \
254                                            connector, connector_state, __i) \
255     for_each_connector_in_state(__state, connector, connector_state, __i)
256 #endif
257 
258 
259 /**
260  * nv_drm_for_each_crtc_in_state - iterate over all CRTCs in an atomic update
261  * @__state: &struct drm_atomic_state pointer
262  * @crtc: &struct drm_crtc iteration cursor
263  * @crtc_state: &struct drm_crtc_state iteration cursor
264  * @__i: int iteration cursor, for macro-internal use
265  *
266  * This iterates over all CRTCs in an atomic update. Note that before the
267  * software state is committed (by calling drm_atomic_helper_swap_state(), this
268  * points to the new state, while afterwards it points to the old state. Due to
269  * this tricky confusion this macro is deprecated.
270  */
271 #if !defined(for_each_crtc_in_state)
272 #define nv_drm_for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
273        for ((__i) = 0;                                                \
274             (__i) < (__state)->dev->mode_config.num_crtc &&           \
275             ((crtc) = (__state)->crtcs[__i].ptr,                      \
276             (crtc_state) = (__state)->crtcs[__i].state, 1);           \
277             (__i)++)                                                  \
278                for_each_if (crtc_state)
279 #else
280 #define nv_drm_for_each_crtc_in_state(__state, crtc, crtc_state, __i) \
281     for_each_crtc_in_state(__state, crtc, crtc_state, __i)
282 #endif
283 
284 /**
285  * nv_drm_for_each_plane_in_state - iterate over all planes in an atomic update
286  * @__state: &struct drm_atomic_state pointer
287  * @plane: &struct drm_plane iteration cursor
288  * @plane_state: &struct drm_plane_state iteration cursor
289  * @__i: int iteration cursor, for macro-internal use
290  *
291  * This iterates over all planes in an atomic update. Note that before the
292  * software state is committed (by calling drm_atomic_helper_swap_state(), this
293  * points to the new state, while afterwards it points to the old state. Due to
294  * this tricky confusion this macro is deprecated.
295  */
296 #if !defined(for_each_plane_in_state)
297 #define nv_drm_for_each_plane_in_state(__state, plane, plane_state, __i) \
298        for ((__i) = 0;                                                   \
299             (__i) < (__state)->dev->mode_config.num_total_plane &&       \
300             ((plane) = (__state)->planes[__i].ptr,                       \
301             (plane_state) = (__state)->planes[__i].state, 1);            \
302             (__i)++)                                                     \
303                for_each_if (plane_state)
304 #else
305 #define nv_drm_for_each_plane_in_state(__state, plane, plane_state, __i) \
306     for_each_plane_in_state(__state, plane, plane_state, __i)
307 #endif
308 
309 static inline struct drm_connector *
310 nv_drm_connector_lookup(struct drm_device *dev, struct drm_file *filep,
311                         uint32_t id)
312 {
313 #if !defined(NV_DRM_CONNECTOR_LOOKUP_PRESENT)
314     return drm_connector_find(dev, id);
315 #elif defined(NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG)
316     return drm_connector_lookup(dev, filep, id);
317 #else
318     return drm_connector_lookup(dev, id);
319 #endif
320 }
321 
322 static inline void nv_drm_connector_put(struct drm_connector *connector)
323 {
324 #if defined(NV_DRM_CONNECTOR_PUT_PRESENT)
325     drm_connector_put(connector);
326 #elif defined(NV_DRM_CONNECTOR_LOOKUP_PRESENT)
327     drm_connector_unreference(connector);
328 #endif
329 }
330 
331 static inline struct drm_crtc *
332 nv_drm_crtc_find(struct drm_device *dev, struct drm_file *filep, uint32_t id)
333 {
334 #if defined(NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG)
335     return drm_crtc_find(dev, filep, id);
336 #else
337     return drm_crtc_find(dev, id);
338 #endif
339 }
340 
341 static inline struct drm_encoder *nv_drm_encoder_find(struct drm_device *dev,
342     uint32_t id)
343 {
344 #if defined(NV_DRM_MODE_OBJECT_FIND_HAS_FILE_PRIV_ARG)
345     return drm_encoder_find(dev, NULL /* file_priv */, id);
346 #else
347     return drm_encoder_find(dev, id);
348 #endif
349 }
350 
351 #if defined(NV_DRM_DRM_AUTH_H_PRESENT)
352 #include <drm/drm_auth.h>
353 #endif
354 #if defined(NV_DRM_DRM_FILE_H_PRESENT)
355 #include <drm/drm_file.h>
356 #endif
357 
358 /*
359  * drm_file_get_master() added by commit 56f0729a510f ("drm: protect drm_master
360  * pointers in drm_lease.c") in v5.15 (2021-07-20)
361  */
362 static inline struct drm_master *nv_drm_file_get_master(struct drm_file *filep)
363 {
364 #if defined(NV_DRM_FILE_GET_MASTER_PRESENT)
365     return drm_file_get_master(filep);
366 #else
367     if (filep->master) {
368         return drm_master_get(filep->master);
369     } else {
370         return NULL;
371     }
372 #endif
373 }
374 
375 /*
376  * drm_connector_for_each_possible_encoder() is added by commit
377  * 83aefbb887b59df0b3520965c3701e01deacfc52 which was Signed-off-by:
378  *     Ville Syrjälä <ville.syrjala@linux.intel.com>
379  *
380  * drm_connector_for_each_possible_encoder() is copied from
381  * include/drm/drm_connector.h and modified to use nv_drm_encoder_find()
382  * instead of drm_encoder_find().
383  *
384  * drm_connector_for_each_possible_encoder() is copied from
385  *      include/drm/drm_connector.h @
386  *      83aefbb887b59df0b3520965c3701e01deacfc52
387  * which has the following copyright and license information:
388  *
389  * Copyright (c) 2016 Intel Corporation
390  *
391  * Permission to use, copy, modify, distribute, and sell this software and its
392  * documentation for any purpose is hereby granted without fee, provided that
393  * the above copyright notice appear in all copies and that both that copyright
394  * notice and this permission notice appear in supporting documentation, and
395  * that the name of the copyright holders not be used in advertising or
396  * publicity pertaining to distribution of the software without specific,
397  * written prior permission.  The copyright holders make no representations
398  * about the suitability of this software for any purpose.  It is provided "as
399  * is" without express or implied warranty.
400  *
401  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
402  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
403  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
404  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
405  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
406  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
407  * OF THIS SOFTWARE.
408  */
409 
410 #if defined(NV_DRM_DRM_CONNECTOR_H_PRESENT)
411 #include <drm/drm_connector.h>
412 #endif
413 
414 /**
415  * nv_drm_connector_for_each_possible_encoder - iterate connector's possible
416  * encoders
417  * @connector: &struct drm_connector pointer
418  * @encoder: &struct drm_encoder pointer used as cursor
419  * @__i: int iteration cursor, for macro-internal use
420  */
421 #if !defined(drm_connector_for_each_possible_encoder)
422 
423 #if !defined(for_each_if)
424 #define for_each_if(condition) if (!(condition)) {} else
425 #endif
426 
427 #define __nv_drm_connector_for_each_possible_encoder(connector, encoder, __i) \
428        for ((__i) = 0; (__i) < ARRAY_SIZE((connector)->encoder_ids) &&        \
429                     (connector)->encoder_ids[(__i)] != 0; (__i)++)            \
430                for_each_if((encoder) =                                        \
431                            nv_drm_encoder_find((connector)->dev,              \
432                                                (connector)->encoder_ids[(__i)]))
433 
434 #define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
435     {                                                                  \
436         unsigned int __i;                                              \
437         __nv_drm_connector_for_each_possible_encoder(connector, encoder, __i)
438 
439 #define nv_drm_connector_for_each_possible_encoder_end \
440     }
441 
442 #else
443 
444 #if NV_DRM_CONNECTOR_FOR_EACH_POSSIBLE_ENCODER_ARGUMENT_COUNT == 3
445 
446 #define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
447     {                                                                  \
448         unsigned int __i;                                              \
449         drm_connector_for_each_possible_encoder(connector, encoder, __i)
450 
451 #define nv_drm_connector_for_each_possible_encoder_end \
452     }
453 
454 #else
455 
456 #define nv_drm_connector_for_each_possible_encoder(connector, encoder) \
457     drm_connector_for_each_possible_encoder(connector, encoder)
458 
459 #define nv_drm_connector_for_each_possible_encoder_end
460 
461 #endif
462 
463 #endif
464 
465 static inline int
466 nv_drm_connector_attach_encoder(struct drm_connector *connector,
467                                 struct drm_encoder *encoder)
468 {
469 #if defined(NV_DRM_CONNECTOR_FUNCS_HAVE_MODE_IN_NAME)
470     return drm_mode_connector_attach_encoder(connector, encoder);
471 #else
472     return drm_connector_attach_encoder(connector, encoder);
473 #endif
474 }
475 
476 static inline int
477 nv_drm_connector_update_edid_property(struct drm_connector *connector,
478                                       const struct edid *edid)
479 {
480 #if defined(NV_DRM_CONNECTOR_FUNCS_HAVE_MODE_IN_NAME)
481     return drm_mode_connector_update_edid_property(connector, edid);
482 #else
483     return drm_connector_update_edid_property(connector, edid);
484 #endif
485 }
486 
487 #if defined(NV_DRM_CONNECTOR_LIST_ITER_PRESENT)
488 #include <drm/drm_connector.h>
489 
490 static inline
491 void nv_drm_connector_list_iter_begin(struct drm_device *dev,
492                                       struct drm_connector_list_iter *iter)
493 {
494 #if defined(NV_DRM_CONNECTOR_LIST_ITER_BEGIN_PRESENT)
495     drm_connector_list_iter_begin(dev, iter);
496 #else
497     drm_connector_list_iter_get(dev, iter);
498 #endif
499 }
500 
501 static inline
502 void nv_drm_connector_list_iter_end(struct drm_connector_list_iter *iter)
503 {
504 #if defined(NV_DRM_CONNECTOR_LIST_ITER_BEGIN_PRESENT)
505     drm_connector_list_iter_end(iter);
506 #else
507     drm_connector_list_iter_put(iter);
508 #endif
509 }
510 #endif
511 
512 /*
513  * The drm_format_num_planes() function was added by commit d0d110e09629 drm:
514  * Add drm_format_num_planes() utility function in v3.3 (2011-12-20). Prototype
515  * was moved from drm_crtc.h to drm_fourcc.h by commit ae4df11a0f53 (drm: Move
516  * format-related helpers to drm_fourcc.c) in v4.8 (2016-06-09).
517  * drm_format_num_planes() has been removed by commit 05c452c115bf (drm: Remove
518  * users of drm_format_num_planes) in v5.3 (2019-05-16).
519  *
520  * drm_format_info() is available only from v4.10 (2016-10-18), added by commit
521  * 84770cc24f3a (drm: Centralize format information).
522  */
523 #include <drm/drm_crtc.h>
524 #include <drm/drm_fourcc.h>
525 
526 static inline int nv_drm_format_num_planes(uint32_t format)
527 {
528 #if defined(NV_DRM_FORMAT_NUM_PLANES_PRESENT)
529     return drm_format_num_planes(format);
530 #else
531     const struct drm_format_info *info = drm_format_info(format);
532     return info != NULL ? info->num_planes : 1;
533 #endif
534 }
535 
536 #if defined(NV_DRM_FORMAT_MODIFIERS_PRESENT)
537 /*
538  * DRM_FORMAT_MOD_LINEAR was also defined after the original modifier support
539  * was added to the kernel, as a more explicit alias of DRM_FORMAT_MOD_NONE
540  */
541 #if !defined(DRM_FORMAT_MOD_VENDOR_NONE)
542 #define DRM_FORMAT_MOD_VENDOR_NONE 0
543 #endif
544 
545 #if !defined(DRM_FORMAT_MOD_LINEAR)
546 #define DRM_FORMAT_MOD_LINEAR fourcc_mod_code(NONE, 0)
547 #endif
548 
549 /*
550  * DRM_FORMAT_MOD_INVALID was defined after the original modifier support was
551  * added to the kernel, for use as a sentinel value.
552  */
553 #if !defined(DRM_FORMAT_RESERVED)
554 #define DRM_FORMAT_RESERVED ((1ULL << 56) - 1)
555 #endif
556 
557 #if !defined(DRM_FORMAT_MOD_INVALID)
558 #define DRM_FORMAT_MOD_INVALID fourcc_mod_code(NONE, DRM_FORMAT_RESERVED)
559 #endif
560 
561 /*
562  * DRM_FORMAT_MOD_VENDOR_NVIDIA was previously called
563  * DRM_FORMAT_MOD_VNEDOR_NV.
564  */
565 #if !defined(DRM_FORMAT_MOD_VENDOR_NVIDIA)
566 #define DRM_FORMAT_MOD_VENDOR_NVIDIA DRM_FORMAT_MOD_VENDOR_NV
567 #endif
568 
569 /*
570  * DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D is a relatively new addition to the
571  * upstream kernel headers compared to the other format modifiers.
572  */
573 #if !defined(DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D)
574 #define DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(c, s, g, k, h) \
575     fourcc_mod_code(NVIDIA, (0x10 | \
576                              ((h) & 0xf) | \
577                              (((k) & 0xff) << 12) | \
578                              (((g) & 0x3) << 20) | \
579                              (((s) & 0x1) << 22) | \
580                              (((c) & 0x7) << 23)))
581 #endif
582 
583 #endif /* defined(NV_DRM_FORMAT_MODIFIERS_PRESENT) */
584 
585 /*
586  * drm_vma_offset_exact_lookup_locked() were added
587  * by kernel commit 2225cfe46bcc which was Signed-off-by:
588  *      Daniel Vetter <daniel.vetter@intel.com>
589  *
590  * drm_vma_offset_exact_lookup_locked() were copied from
591  *      include/drm/drm_vma_manager.h @ 2225cfe46bcc
592  * which has the following copyright and license information:
593  *
594  * Copyright (c) 2013 David Herrmann <dh.herrmann@gmail.com>
595  *
596  * Permission is hereby granted, free of charge, to any person obtaining a
597  * copy of this software and associated documentation files (the "Software"),
598  * to deal in the Software without restriction, including without limitation
599  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
600  * and/or sell copies of the Software, and to permit persons to whom the
601  * Software is furnished to do so, subject to the following conditions:
602  *
603  * The above copyright notice and this permission notice shall be included in
604  * all copies or substantial portions of the Software.
605  *
606  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
607  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
608  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
609  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
610  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
611  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
612  * OTHER DEALINGS IN THE SOFTWARE.
613  */
614 
615 #include <drm/drm_vma_manager.h>
616 
617 /**
618  * nv_drm_vma_offset_exact_lookup_locked() - Look up node by exact address
619  * @mgr: Manager object
620  * @start: Start address (page-based, not byte-based)
621  * @pages: Size of object (page-based)
622  *
623  * Same as drm_vma_offset_lookup_locked() but does not allow any offset into the node.
624  * It only returns the exact object with the given start address.
625  *
626  * RETURNS:
627  * Node at exact start address @start.
628  */
629 static inline struct drm_vma_offset_node *
630 nv_drm_vma_offset_exact_lookup_locked(struct drm_vma_offset_manager *mgr,
631                                       unsigned long start,
632                                       unsigned long pages)
633 {
634 #if defined(NV_DRM_VMA_OFFSET_EXACT_LOOKUP_LOCKED_PRESENT)
635     return drm_vma_offset_exact_lookup_locked(mgr, start, pages);
636 #else
637     struct drm_vma_offset_node *node;
638 
639     node = drm_vma_offset_lookup_locked(mgr, start, pages);
640     return (node && node->vm_node.start == start) ? node : NULL;
641 #endif
642 }
643 
644 static inline bool
645 nv_drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
646                            struct file *filp)
647 {
648 #if defined(NV_DRM_VMA_NODE_IS_ALLOWED_HAS_TAG_ARG)
649     return drm_vma_node_is_allowed(node, filp->private_data);
650 #else
651     return drm_vma_node_is_allowed(node, filp);
652 #endif
653 }
654 
655 #endif /* defined(NV_DRM_ATOMIC_MODESET_AVAILABLE) */
656 
657 #endif /* defined(NV_DRM_AVAILABLE) */
658 
659 #endif /* __NVIDIA_DRM_HELPER_H__ */
660