• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22 
23 #include <linux/uaccess.h>
24 
25 #include <drm/drm_drv.h>
26 #include <drm/drm_encoder.h>
27 #include <drm/drm_file.h>
28 #include <drm/drm_managed.h>
29 #include <drm/drm_mode_config.h>
30 #include <drm/drm_print.h>
31 #include <linux/dma-resv.h>
32 
33 #include "drm_crtc_internal.h"
34 #include "drm_internal.h"
35 
drm_modeset_register_all(struct drm_device * dev)36 int drm_modeset_register_all(struct drm_device *dev)
37 {
38     int ret;
39 
40     ret = drm_plane_register_all(dev);
41     if (ret) {
42         goto err_plane;
43     }
44 
45     ret = drm_crtc_register_all(dev);
46     if (ret) {
47         goto err_crtc;
48     }
49 
50     ret = drm_encoder_register_all(dev);
51     if (ret) {
52         goto err_encoder;
53     }
54 
55     ret = drm_connector_register_all(dev);
56     if (ret) {
57         goto err_connector;
58     }
59 
60     return 0;
61 
62 err_connector:
63     drm_encoder_unregister_all(dev);
64 err_encoder:
65     drm_crtc_unregister_all(dev);
66 err_crtc:
67     drm_plane_unregister_all(dev);
68 err_plane:
69     return ret;
70 }
71 
drm_modeset_unregister_all(struct drm_device * dev)72 void drm_modeset_unregister_all(struct drm_device *dev)
73 {
74     drm_connector_unregister_all(dev);
75     drm_encoder_unregister_all(dev);
76     drm_crtc_unregister_all(dev);
77     drm_plane_unregister_all(dev);
78 }
79 
80 /**
81  * drm_mode_getresources - get graphics configuration
82  * @dev: drm device for the ioctl
83  * @data: data pointer for the ioctl
84  * @file_priv: drm file for the ioctl call
85  *
86  * Construct a set of configuration description structures and return
87  * them to the user, including CRTC, connector and framebuffer configuration.
88  *
89  * Called by the user via ioctl.
90  *
91  * Returns:
92  * Zero on success, negative errno on failure.
93  */
drm_mode_getresources(struct drm_device * dev,void * data,struct drm_file * file_priv)94 int drm_mode_getresources(struct drm_device *dev, void *data, struct drm_file *file_priv)
95 {
96     struct drm_mode_card_res *card_res = data;
97     struct drm_framebuffer *fb;
98     struct drm_connector *connector;
99     struct drm_crtc *crtc;
100     struct drm_encoder *encoder;
101     int count, ret = 0;
102     uint32_t __user *fb_id;
103     uint32_t __user *crtc_id;
104     uint32_t __user *connector_id;
105     uint32_t __user *encoder_id;
106     struct drm_connector_list_iter conn_iter;
107 
108     if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
109         return -EOPNOTSUPP;
110     }
111 
112     mutex_lock(&file_priv->fbs_lock);
113     count = 0;
114     fb_id = u64_to_user_ptr(card_res->fb_id_ptr);
115     list_for_each_entry(fb, &file_priv->fbs, filp_head)
116     {
117         if (count < card_res->count_fbs && put_user(fb->base.id, fb_id + count)) {
118             mutex_unlock(&file_priv->fbs_lock);
119             return -EFAULT;
120         }
121         count++;
122     }
123     card_res->count_fbs = count;
124     mutex_unlock(&file_priv->fbs_lock);
125 
126     card_res->max_height = dev->mode_config.max_height;
127     card_res->min_height = dev->mode_config.min_height;
128     card_res->max_width = dev->mode_config.max_width;
129     card_res->min_width = dev->mode_config.min_width;
130 
131     count = 0;
132     crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
133     drm_for_each_crtc(crtc, dev)
134     {
135         if (drm_lease_held(file_priv, crtc->base.id)) {
136             if (count < card_res->count_crtcs && put_user(crtc->base.id, crtc_id + count)) {
137                 return -EFAULT;
138             }
139             count++;
140         }
141     }
142     card_res->count_crtcs = count;
143 
144     count = 0;
145     encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
146     drm_for_each_encoder(encoder, dev)
147     {
148         if (count < card_res->count_encoders && put_user(encoder->base.id, encoder_id + count)) {
149             return -EFAULT;
150         }
151         count++;
152     }
153     card_res->count_encoders = count;
154 
155     drm_connector_list_iter_begin(dev, &conn_iter);
156     count = 0;
157     connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
158     drm_for_each_connector_iter(connector, &conn_iter)
159     {
160         /* only expose writeback connectors if userspace understands them */
161         if (!file_priv->writeback_connectors && (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK)) {
162             continue;
163         }
164 
165         if (drm_lease_held(file_priv, connector->base.id)) {
166             if (count < card_res->count_connectors && put_user(connector->base.id, connector_id + count)) {
167                 drm_connector_list_iter_end(&conn_iter);
168                 return -EFAULT;
169             }
170             count++;
171         }
172     }
173     card_res->count_connectors = count;
174     drm_connector_list_iter_end(&conn_iter);
175 
176     return ret;
177 }
178 
179 /**
180  * drm_mode_config_reset - call ->reset callbacks
181  * @dev: drm device
182  *
183  * This functions calls all the crtc's, encoder's and connector's ->reset
184  * callback. Drivers can use this in e.g. their driver load or resume code to
185  * reset hardware and software state.
186  */
drm_mode_config_reset(struct drm_device * dev)187 void drm_mode_config_reset(struct drm_device *dev)
188 {
189     struct drm_crtc *crtc;
190     struct drm_plane *plane;
191     struct drm_encoder *encoder;
192     struct drm_connector *connector;
193     struct drm_connector_list_iter conn_iter;
194 
195     drm_for_each_plane(plane, dev) if (plane->funcs->reset) plane->funcs->reset(plane);
196 
197     drm_for_each_crtc(crtc, dev) if (crtc->funcs->reset) crtc->funcs->reset(crtc);
198 
199     drm_for_each_encoder(encoder, dev) if (encoder->funcs->reset) encoder->funcs->reset(encoder);
200 
201     drm_connector_list_iter_begin(dev, &conn_iter);
202     drm_for_each_connector_iter(connector, &conn_iter) if (connector->funcs->reset) connector->funcs->reset(connector);
203     drm_connector_list_iter_end(&conn_iter);
204 }
205 EXPORT_SYMBOL(drm_mode_config_reset);
206 
207 /*
208  * Global properties
209  */
210 static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
211     {DRM_PLANE_TYPE_OVERLAY, "Overlay"},
212     {DRM_PLANE_TYPE_PRIMARY, "Primary"},
213     {DRM_PLANE_TYPE_CURSOR, "Cursor"},
214 };
215 
drm_mode_create_standard_properties(struct drm_device * dev)216 static int drm_mode_create_standard_properties(struct drm_device *dev)
217 {
218     struct drm_property *prop;
219     int ret;
220 
221     ret = drm_connector_create_standard_properties(dev);
222     if (ret) {
223         return ret;
224     }
225 
226     prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, "type", drm_plane_type_enum_list,
227                                     ARRAY_SIZE(drm_plane_type_enum_list));
228     if (!prop) {
229         return -ENOMEM;
230     }
231     dev->mode_config.plane_type_property = prop;
232 
233     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SRC_X", 0, UINT_MAX);
234     if (!prop) {
235         return -ENOMEM;
236     }
237     dev->mode_config.prop_src_x = prop;
238 
239     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SRC_Y", 0, UINT_MAX);
240     if (!prop) {
241         return -ENOMEM;
242     }
243     dev->mode_config.prop_src_y = prop;
244 
245     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SRC_W", 0, UINT_MAX);
246     if (!prop) {
247         return -ENOMEM;
248     }
249     dev->mode_config.prop_src_w = prop;
250 
251     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "SRC_H", 0, UINT_MAX);
252     if (!prop) {
253         return -ENOMEM;
254     }
255     dev->mode_config.prop_src_h = prop;
256 
257     prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, "CRTC_X", INT_MIN, INT_MAX);
258     if (!prop) {
259         return -ENOMEM;
260     }
261     dev->mode_config.prop_crtc_x = prop;
262 
263     prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, "CRTC_Y", INT_MIN, INT_MAX);
264     if (!prop) {
265         return -ENOMEM;
266     }
267     dev->mode_config.prop_crtc_y = prop;
268 
269     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "CRTC_W", 0, INT_MAX);
270     if (!prop) {
271         return -ENOMEM;
272     }
273     dev->mode_config.prop_crtc_w = prop;
274 
275     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "CRTC_H", 0, INT_MAX);
276     if (!prop) {
277         return -ENOMEM;
278     }
279     dev->mode_config.prop_crtc_h = prop;
280 
281     prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, "FB_ID", DRM_MODE_OBJECT_FB);
282     if (!prop) {
283         return -ENOMEM;
284     }
285     dev->mode_config.prop_fb_id = prop;
286 
287     prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, "IN_FENCE_FD", -1, INT_MAX);
288     if (!prop) {
289         return -ENOMEM;
290     }
291     dev->mode_config.prop_in_fence_fd = prop;
292 
293     prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, "OUT_FENCE_PTR", 0, U64_MAX);
294     if (!prop) {
295         return -ENOMEM;
296     }
297     dev->mode_config.prop_out_fence_ptr = prop;
298 
299     prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, "CRTC_ID", DRM_MODE_OBJECT_CRTC);
300     if (!prop) {
301         return -ENOMEM;
302     }
303     dev->mode_config.prop_crtc_id = prop;
304 
305     prop = drm_property_create(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB, "FB_DAMAGE_CLIPS", 0);
306     if (!prop) {
307         return -ENOMEM;
308     }
309     dev->mode_config.prop_fb_damage_clips = prop;
310 
311     prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC, "ACTIVE");
312     if (!prop) {
313         return -ENOMEM;
314     }
315     dev->mode_config.prop_active = prop;
316 
317     prop = drm_property_create(dev, DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB, "MODE_ID", 0);
318     if (!prop) {
319         return -ENOMEM;
320     }
321     dev->mode_config.prop_mode_id = prop;
322 
323     prop = drm_property_create_bool(dev, 0, "VRR_ENABLED");
324     if (!prop) {
325         return -ENOMEM;
326     }
327     dev->mode_config.prop_vrr_enabled = prop;
328 
329     prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "DEGAMMA_LUT", 0);
330     if (!prop) {
331         return -ENOMEM;
332     }
333     dev->mode_config.degamma_lut_property = prop;
334 
335     prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "DEGAMMA_LUT_SIZE", 0, UINT_MAX);
336     if (!prop) {
337         return -ENOMEM;
338     }
339     dev->mode_config.degamma_lut_size_property = prop;
340 
341     prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CTM", 0);
342     if (!prop) {
343         return -ENOMEM;
344     }
345     dev->mode_config.ctm_property = prop;
346 
347     prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "GAMMA_LUT", 0);
348     if (!prop) {
349         return -ENOMEM;
350     }
351     dev->mode_config.gamma_lut_property = prop;
352 
353     prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "GAMMA_LUT_SIZE", 0, UINT_MAX);
354     if (!prop) {
355         return -ENOMEM;
356     }
357     dev->mode_config.gamma_lut_size_property = prop;
358 
359 #if defined(CONFIG_ROCKCHIP_DRM_CUBIC_LUT)
360     prop = drm_property_create(dev, DRM_MODE_PROP_BLOB, "CUBIC_LUT", 0);
361     if (!prop) {
362         return -ENOMEM;
363     }
364     dev->mode_config.cubic_lut_property = prop;
365 
366     prop = drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "CUBIC_LUT_SIZE", 0, UINT_MAX);
367     if (!prop) {
368         return -ENOMEM;
369     }
370     dev->mode_config.cubic_lut_size_property = prop;
371 #endif
372 
373     prop = drm_property_create(dev, DRM_MODE_PROP_IMMUTABLE | DRM_MODE_PROP_BLOB, "IN_FORMATS", 0);
374     if (!prop) {
375         return -ENOMEM;
376     }
377     dev->mode_config.modifiers_property = prop;
378 
379     return 0;
380 }
381 
drm_mode_config_init_release(struct drm_device * dev,void * ptr)382 static void drm_mode_config_init_release(struct drm_device *dev, void *ptr)
383 {
384     drm_mode_config_cleanup(dev);
385 }
386 
387 /**
388  * drmm_mode_config_init - managed DRM mode_configuration structure
389  *     initialization
390  * @dev: DRM device
391  *
392  * Initialize @dev's mode_config structure, used for tracking the graphics
393  * configuration of @dev.
394  *
395  * Since this initializes the modeset locks, no locking is possible. Which is no
396  * problem, since this should happen single threaded at init time. It is the
397  * driver's problem to ensure this guarantee.
398  *
399  * Cleanup is automatically handled through registering drm_mode_config_cleanup
400  * with drmm_add_action().
401  *
402  * Returns: 0 on success, negative error value on failure.
403  */
drmm_mode_config_init(struct drm_device * dev)404 int drmm_mode_config_init(struct drm_device *dev)
405 {
406     mutex_init(&dev->mode_config.mutex);
407     drm_modeset_lock_init(&dev->mode_config.connection_mutex);
408     mutex_init(&dev->mode_config.idr_mutex);
409     mutex_init(&dev->mode_config.fb_lock);
410     mutex_init(&dev->mode_config.blob_lock);
411     INIT_LIST_HEAD(&dev->mode_config.fb_list);
412     INIT_LIST_HEAD(&dev->mode_config.crtc_list);
413     INIT_LIST_HEAD(&dev->mode_config.connector_list);
414     INIT_LIST_HEAD(&dev->mode_config.encoder_list);
415     INIT_LIST_HEAD(&dev->mode_config.property_list);
416     INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
417     INIT_LIST_HEAD(&dev->mode_config.plane_list);
418     INIT_LIST_HEAD(&dev->mode_config.privobj_list);
419     idr_init(&dev->mode_config.object_idr);
420     idr_init(&dev->mode_config.tile_idr);
421     ida_init(&dev->mode_config.connector_ida);
422     spin_lock_init(&dev->mode_config.connector_list_lock);
423 
424     init_llist_head(&dev->mode_config.connector_free_list);
425     INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn);
426 
427     drm_mode_create_standard_properties(dev);
428 
429     /* Just to be sure */
430     dev->mode_config.num_fb = 0;
431     dev->mode_config.num_connector = 0;
432     dev->mode_config.num_crtc = 0;
433     dev->mode_config.num_encoder = 0;
434     dev->mode_config.num_total_plane = 0;
435 
436     if (IS_ENABLED(CONFIG_LOCKDEP)) {
437         struct drm_modeset_acquire_ctx modeset_ctx;
438         struct ww_acquire_ctx resv_ctx;
439         struct dma_resv resv;
440         int ret;
441 
442         dma_resv_init(&resv);
443 
444         drm_modeset_acquire_init(&modeset_ctx, 0);
445         ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &modeset_ctx);
446         if (ret == -EDEADLK) {
447             ret = drm_modeset_backoff(&modeset_ctx);
448         }
449 
450         ww_acquire_init(&resv_ctx, &reservation_ww_class);
451         ret = dma_resv_lock(&resv, &resv_ctx);
452         if (ret == -EDEADLK) {
453             dma_resv_lock_slow(&resv, &resv_ctx);
454         }
455 
456         dma_resv_unlock(&resv);
457         ww_acquire_fini(&resv_ctx);
458 
459         drm_modeset_drop_locks(&modeset_ctx);
460         drm_modeset_acquire_fini(&modeset_ctx);
461         dma_resv_fini(&resv);
462     }
463 
464     return drmm_add_action_or_reset(dev, drm_mode_config_init_release, NULL);
465 }
466 EXPORT_SYMBOL(drmm_mode_config_init);
467 
468 /**
469  * drm_mode_config_cleanup - free up DRM mode_config info
470  * @dev: DRM device
471  *
472  * Free up all the connectors and CRTCs associated with this DRM device, then
473  * free up the framebuffers and associated buffer objects.
474  *
475  * Note that since this /should/ happen single-threaded at driver/device
476  * teardown time, no locking is required. It's the driver's job to ensure that
477  * this guarantee actually holds true.
478  *
479  * With the managed drmm_mode_config_init() it is no longer necessary for
480  * drivers to explicitly call this function.
481  */
drm_mode_config_cleanup(struct drm_device * dev)482 void drm_mode_config_cleanup(struct drm_device *dev)
483 {
484     struct drm_connector *connector;
485     struct drm_connector_list_iter conn_iter;
486     struct drm_crtc *crtc, *ct;
487     struct drm_encoder *encoder, *enct;
488     struct drm_framebuffer *fb, *fbt;
489     struct drm_property *property, *pt;
490     struct drm_property_blob *blob, *bt;
491     struct drm_plane *plane, *plt;
492 
493     list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, head)
494     {
495         encoder->funcs->destroy(encoder);
496     }
497 
498     drm_connector_list_iter_begin(dev, &conn_iter);
499     drm_for_each_connector_iter(connector, &conn_iter)
500     {
501         /* drm_connector_list_iter holds an full reference to the
502          * current connector itself, which means it is inherently safe
503          * against unreferencing the current connector - but not against
504          * deleting it right away. */
505         drm_connector_put(connector);
506     }
507     drm_connector_list_iter_end(&conn_iter);
508     /* connector_iter drops references in a work item. */
509     flush_work(&dev->mode_config.connector_free_work);
510     if (WARN_ON(!list_empty(&dev->mode_config.connector_list))) {
511         drm_connector_list_iter_begin(dev, &conn_iter);
512         drm_for_each_connector_iter(connector, &conn_iter) DRM_ERROR("connector %s leaked!\n", connector->name);
513         drm_connector_list_iter_end(&conn_iter);
514     }
515 
516     list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, head)
517     {
518         drm_property_destroy(dev, property);
519     }
520 
521     list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, head)
522     {
523         plane->funcs->destroy(plane);
524     }
525 
526     list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head)
527     {
528         crtc->funcs->destroy(crtc);
529     }
530 
531     list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, head_global)
532     {
533         drm_property_blob_put(blob);
534     }
535 
536     /*
537      * Single-threaded teardown context, so it's not required to grab the
538      * fb_lock to protect against concurrent fb_list access. Contrary, it
539      * would actually deadlock with the drm_framebuffer_cleanup function.
540      *
541      * Also, if there are any framebuffers left, that's a driver leak now,
542      * so politely WARN about this.
543      */
544     WARN_ON(!list_empty(&dev->mode_config.fb_list));
545     list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head)
546     {
547         struct drm_printer p = drm_debug_printer("[leaked fb]");
548 
549         drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
550         drm_framebuffer_print_info(&p, 1, fb);
551         drm_framebuffer_free(&fb->base.refcount);
552     }
553 
554     ida_destroy(&dev->mode_config.connector_ida);
555     idr_destroy(&dev->mode_config.tile_idr);
556     idr_destroy(&dev->mode_config.object_idr);
557     drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
558 }
559 EXPORT_SYMBOL(drm_mode_config_cleanup);
560 
full_encoder_mask(struct drm_device * dev)561 static u32 full_encoder_mask(struct drm_device *dev)
562 {
563     struct drm_encoder *encoder;
564     u32 encoder_mask = 0;
565 
566     drm_for_each_encoder(encoder, dev) encoder_mask |= drm_encoder_mask(encoder);
567 
568     return encoder_mask;
569 }
570 
571 /*
572  * For some reason we want the encoder itself included in
573  * possible_clones. Make life easy for drivers by allowing them
574  * to leave possible_clones unset if no cloning is possible.
575  */
fixup_encoder_possible_clones(struct drm_encoder * encoder)576 static void fixup_encoder_possible_clones(struct drm_encoder *encoder)
577 {
578     if (encoder->possible_clones == 0) {
579         encoder->possible_clones = drm_encoder_mask(encoder);
580     }
581 }
582 
validate_encoder_possible_clones(struct drm_encoder * encoder)583 static void validate_encoder_possible_clones(struct drm_encoder *encoder)
584 {
585     struct drm_device *dev = encoder->dev;
586     u32 encoder_mask = full_encoder_mask(dev);
587     struct drm_encoder *other;
588 
589     drm_for_each_encoder(other, dev)
590     {
591         WARN(!!(encoder->possible_clones & drm_encoder_mask(other)) !=
592                  !!(other->possible_clones & drm_encoder_mask(encoder)),
593              "possible_clones mismatch: "
594              "[ENCODER:%d:%s] mask=0x%x possible_clones=0x%x vs. "
595              "[ENCODER:%d:%s] mask=0x%x possible_clones=0x%x\n",
596              encoder->base.id, encoder->name, drm_encoder_mask(encoder), encoder->possible_clones, other->base.id,
597              other->name, drm_encoder_mask(other), other->possible_clones);
598     }
599 
600     WARN((encoder->possible_clones & drm_encoder_mask(encoder)) == 0 || (encoder->possible_clones & ~encoder_mask) != 0,
601          "Bogus possible_clones: "
602          "[ENCODER:%d:%s] possible_clones=0x%x (full encoder mask=0x%x)\n",
603          encoder->base.id, encoder->name, encoder->possible_clones, encoder_mask);
604 }
605 
full_crtc_mask(struct drm_device * dev)606 static u32 full_crtc_mask(struct drm_device *dev)
607 {
608     struct drm_crtc *crtc;
609     u32 crtc_mask = 0;
610 
611     drm_for_each_crtc(crtc, dev) crtc_mask |= drm_crtc_mask(crtc);
612 
613     return crtc_mask;
614 }
615 
validate_encoder_possible_crtcs(struct drm_encoder * encoder)616 static void validate_encoder_possible_crtcs(struct drm_encoder *encoder)
617 {
618     u32 crtc_mask = full_crtc_mask(encoder->dev);
619 
620     WARN((encoder->possible_crtcs & crtc_mask) == 0 || (encoder->possible_crtcs & ~crtc_mask) != 0,
621          "Bogus possible_crtcs: "
622          "[ENCODER:%d:%s] possible_crtcs=0x%x (full crtc mask=0x%x)\n",
623          encoder->base.id, encoder->name, encoder->possible_crtcs, crtc_mask);
624 }
625 
drm_mode_config_validate(struct drm_device * dev)626 void drm_mode_config_validate(struct drm_device *dev)
627 {
628     struct drm_encoder *encoder;
629 
630     if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
631         return;
632     }
633 
634     drm_for_each_encoder(encoder, dev) fixup_encoder_possible_clones(encoder);
635 
636     drm_for_each_encoder(encoder, dev)
637     {
638         validate_encoder_possible_clones(encoder);
639         validate_encoder_possible_crtcs(encoder);
640     }
641 }
642