Rev 5367 | Rev 6088 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5367 | Rev 6084 | ||
---|---|---|---|
Line 36... | Line 36... | ||
36 | #include |
36 | #include |
37 | #include |
37 | #include |
38 | #include |
38 | #include |
39 | #include |
39 | #include |
40 | #include |
40 | #include |
- | 41 | #include |
|
Line 41... | Line 42... | ||
41 | 42 | ||
42 | #include "drm_crtc_internal.h" |
43 | #include "drm_crtc_internal.h" |
Line -... | Line 44... | ||
- | 44 | #include "drm_internal.h" |
|
43 | #include "drm_internal.h" |
45 | |
44 | 46 | static struct drm_framebuffer * |
|
45 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, |
47 | internal_framebuffer_create(struct drm_device *dev, |
Line 46... | Line 48... | ||
46 | struct drm_mode_fb_cmd2 *r, |
48 | struct drm_mode_fb_cmd2 *r, |
47 | struct drm_file *file_priv); |
49 | struct drm_file *file_priv); |
Line 59... | Line 61... | ||
59 | } |
61 | } |
Line 60... | Line 62... | ||
60 | 62 | ||
61 | /* |
63 | /* |
62 | * Global properties |
64 | * Global properties |
63 | */ |
65 | */ |
64 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = |
66 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = { |
65 | { { DRM_MODE_DPMS_ON, "On" }, |
67 | { DRM_MODE_DPMS_ON, "On" }, |
66 | { DRM_MODE_DPMS_STANDBY, "Standby" }, |
68 | { DRM_MODE_DPMS_STANDBY, "Standby" }, |
67 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, |
69 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, |
68 | { DRM_MODE_DPMS_OFF, "Off" } |
70 | { DRM_MODE_DPMS_OFF, "Off" } |
Line 69... | Line 71... | ||
69 | }; |
71 | }; |
Line 70... | Line 72... | ||
70 | 72 | ||
71 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) |
- | |
72 | 73 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) |
|
73 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = |
74 | |
74 | { |
75 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { |
75 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, |
76 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, |
Line 76... | Line 77... | ||
76 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, |
77 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, |
77 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, |
78 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, |
78 | }; |
79 | }; |
79 | 80 | ||
80 | /* |
- | |
81 | * Optional properties |
81 | /* |
82 | */ |
82 | * Optional properties |
83 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = |
83 | */ |
84 | { |
84 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { |
85 | { DRM_MODE_SCALE_NONE, "None" }, |
85 | { DRM_MODE_SCALE_NONE, "None" }, |
Line 95... | Line 95... | ||
95 | }; |
95 | }; |
Line 96... | Line 96... | ||
96 | 96 | ||
97 | /* |
97 | /* |
98 | * Non-global properties, but "required" for certain connectors. |
98 | * Non-global properties, but "required" for certain connectors. |
99 | */ |
99 | */ |
100 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = |
- | |
101 | { |
100 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { |
102 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
101 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
103 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
102 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
104 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
103 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
Line 105... | Line 104... | ||
105 | }; |
104 | }; |
Line 106... | Line 105... | ||
106 | 105 | ||
107 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
- | |
108 | 106 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
|
109 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = |
107 | |
110 | { |
108 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { |
111 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
109 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
Line 112... | Line 110... | ||
112 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
110 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
113 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
111 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
Line 114... | Line 112... | ||
114 | }; |
112 | }; |
115 | - | ||
116 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, |
113 | |
117 | drm_dvi_i_subconnector_enum_list) |
114 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, |
118 | 115 | drm_dvi_i_subconnector_enum_list) |
|
119 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = |
116 | |
120 | { |
117 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { |
121 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
118 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
Line 122... | Line 119... | ||
122 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
119 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
Line 123... | Line 120... | ||
123 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
120 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
124 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
- | |
125 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
121 | { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ |
126 | }; |
122 | { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ |
127 | 123 | }; |
|
128 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
124 | |
129 | 125 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
|
Line 152... | Line 148... | ||
152 | }; |
148 | }; |
Line 153... | Line 149... | ||
153 | 149 | ||
154 | /* |
150 | /* |
155 | * Connector and encoder types. |
151 | * Connector and encoder types. |
156 | */ |
152 | */ |
157 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = |
153 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { |
158 | { { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, |
154 | { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, |
159 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, |
155 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, |
160 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, |
156 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, |
161 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, |
157 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, |
162 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, |
158 | { DRM_MODE_CONNECTOR_DVIA, "DVI-A" }, |
Line 172... | Line 168... | ||
172 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, |
168 | { DRM_MODE_CONNECTOR_eDP, "eDP" }, |
173 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, |
169 | { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" }, |
174 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, |
170 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, |
175 | }; |
171 | }; |
Line 176... | Line 172... | ||
176 | 172 | ||
177 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = |
173 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = { |
178 | { { DRM_MODE_ENCODER_NONE, "None" }, |
174 | { DRM_MODE_ENCODER_NONE, "None" }, |
179 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
175 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
180 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
176 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
181 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
177 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
182 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
178 | { DRM_MODE_ENCODER_TVDAC, "TV" }, |
183 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, |
179 | { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, |
184 | { DRM_MODE_ENCODER_DSI, "DSI" }, |
180 | { DRM_MODE_ENCODER_DSI, "DSI" }, |
185 | { DRM_MODE_ENCODER_DPMST, "DP MST" }, |
181 | { DRM_MODE_ENCODER_DPMST, "DP MST" }, |
Line 186... | Line 182... | ||
186 | }; |
182 | }; |
187 | - | ||
188 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = |
183 | |
189 | { |
184 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { |
190 | { SubPixelUnknown, "Unknown" }, |
185 | { SubPixelUnknown, "Unknown" }, |
191 | { SubPixelHorizontalRGB, "Horizontal RGB" }, |
186 | { SubPixelHorizontalRGB, "Horizontal RGB" }, |
192 | { SubPixelHorizontalBGR, "Horizontal BGR" }, |
187 | { SubPixelHorizontalBGR, "Horizontal BGR" }, |
Line 309... | Line 304... | ||
309 | * for tracking modes, CRTCs and connectors. Note that despite the _get postfix |
304 | * for tracking modes, CRTCs and connectors. Note that despite the _get postfix |
310 | * modeset identifiers are _not_ reference counted. Hence don't use this for |
305 | * modeset identifiers are _not_ reference counted. Hence don't use this for |
311 | * reference counted modeset objects like framebuffers. |
306 | * reference counted modeset objects like framebuffers. |
312 | * |
307 | * |
313 | * Returns: |
308 | * Returns: |
314 | * New unique (relative to other objects in @dev) integer identifier for the |
309 | * Zero on success, error code on failure. |
315 | * object. |
- | |
316 | */ |
310 | */ |
317 | int drm_mode_object_get(struct drm_device *dev, |
311 | int drm_mode_object_get(struct drm_device *dev, |
318 | struct drm_mode_object *obj, uint32_t obj_type) |
312 | struct drm_mode_object *obj, uint32_t obj_type) |
319 | { |
313 | { |
320 | return drm_mode_object_get_reg(dev, obj, obj_type, true); |
314 | return drm_mode_object_get_reg(dev, obj, obj_type, true); |
Line 355... | Line 349... | ||
355 | if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) |
349 | if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type) |
356 | obj = NULL; |
350 | obj = NULL; |
357 | if (obj && obj->id != id) |
351 | if (obj && obj->id != id) |
358 | obj = NULL; |
352 | obj = NULL; |
359 | /* don't leak out unref'd fb's */ |
353 | /* don't leak out unref'd fb's */ |
- | 354 | if (obj && |
|
360 | if (obj && (obj->type == DRM_MODE_OBJECT_FB)) |
355 | (obj->type == DRM_MODE_OBJECT_FB || |
- | 356 | obj->type == DRM_MODE_OBJECT_BLOB)) |
|
361 | obj = NULL; |
357 | obj = NULL; |
362 | mutex_unlock(&dev->mode_config.idr_mutex); |
358 | mutex_unlock(&dev->mode_config.idr_mutex); |
Line 363... | Line 359... | ||
363 | 359 | ||
364 | return obj; |
360 | return obj; |
Line 380... | Line 376... | ||
380 | { |
376 | { |
381 | struct drm_mode_object *obj = NULL; |
377 | struct drm_mode_object *obj = NULL; |
Line 382... | Line 378... | ||
382 | 378 | ||
383 | /* Framebuffers are reference counted and need their own lookup |
379 | /* Framebuffers are reference counted and need their own lookup |
384 | * function.*/ |
380 | * function.*/ |
385 | WARN_ON(type == DRM_MODE_OBJECT_FB); |
381 | WARN_ON(type == DRM_MODE_OBJECT_FB || type == DRM_MODE_OBJECT_BLOB); |
386 | obj = _object_find(dev, id, type); |
382 | obj = _object_find(dev, id, type); |
387 | return obj; |
383 | return obj; |
388 | } |
384 | } |
Line 424... | Line 420... | ||
424 | dev->mode_config.num_fb++; |
420 | dev->mode_config.num_fb++; |
425 | list_add(&fb->head, &dev->mode_config.fb_list); |
421 | list_add(&fb->head, &dev->mode_config.fb_list); |
426 | out: |
422 | out: |
427 | mutex_unlock(&dev->mode_config.fb_lock); |
423 | mutex_unlock(&dev->mode_config.fb_lock); |
Line 428... | Line 424... | ||
428 | 424 | ||
429 | return 0; |
425 | return ret; |
430 | } |
426 | } |
Line 431... | Line 427... | ||
431 | EXPORT_SYMBOL(drm_framebuffer_init); |
427 | EXPORT_SYMBOL(drm_framebuffer_init); |
432 | 428 | ||
Line 492... | Line 488... | ||
492 | { |
488 | { |
493 | struct drm_framebuffer *fb; |
489 | struct drm_framebuffer *fb; |
Line 494... | Line 490... | ||
494 | 490 | ||
495 | mutex_lock(&dev->mode_config.fb_lock); |
491 | mutex_lock(&dev->mode_config.fb_lock); |
496 | fb = __drm_framebuffer_lookup(dev, id); |
492 | fb = __drm_framebuffer_lookup(dev, id); |
497 | if (fb) |
493 | if (fb) { |
- | 494 | if (!kref_get_unless_zero(&fb->refcount)) |
|
- | 495 | fb = NULL; |
|
498 | drm_framebuffer_reference(fb); |
496 | } |
Line 499... | Line 497... | ||
499 | mutex_unlock(&dev->mode_config.fb_lock); |
497 | mutex_unlock(&dev->mode_config.fb_lock); |
500 | 498 | ||
501 | return fb; |
499 | return fb; |
Line 526... | Line 524... | ||
526 | DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount)); |
524 | DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount)); |
527 | kref_get(&fb->refcount); |
525 | kref_get(&fb->refcount); |
528 | } |
526 | } |
529 | EXPORT_SYMBOL(drm_framebuffer_reference); |
527 | EXPORT_SYMBOL(drm_framebuffer_reference); |
Line 530... | Line -... | ||
530 | - | ||
531 | static void drm_framebuffer_free_bug(struct kref *kref) |
- | |
532 | { |
- | |
533 | BUG(); |
- | |
534 | } |
- | |
535 | - | ||
536 | static void __drm_framebuffer_unreference(struct drm_framebuffer *fb) |
- | |
537 | { |
- | |
538 | DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount)); |
- | |
539 | kref_put(&fb->refcount, drm_framebuffer_free_bug); |
- | |
540 | } |
- | |
541 | 528 | ||
542 | /** |
529 | /** |
543 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr |
530 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr |
544 | * @fb: fb to unregister |
531 | * @fb: fb to unregister |
545 | * |
532 | * |
Line 548... | Line 535... | ||
548 | * i.e. the object may not be destroyed through this call (since it'll lead to a |
535 | * i.e. the object may not be destroyed through this call (since it'll lead to a |
549 | * locking inversion). |
536 | * locking inversion). |
550 | */ |
537 | */ |
551 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) |
538 | void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) |
552 | { |
539 | { |
553 | struct drm_device *dev = fb->dev; |
540 | struct drm_device *dev; |
- | 541 | ||
- | 542 | if (!fb) |
|
- | 543 | return; |
|
- | 544 | ||
- | 545 | dev = fb->dev; |
|
Line 554... | Line 546... | ||
554 | 546 | ||
555 | mutex_lock(&dev->mode_config.fb_lock); |
547 | mutex_lock(&dev->mode_config.fb_lock); |
556 | /* Mark fb as reaped and drop idr ref. */ |
548 | /* Mark fb as reaped and drop idr ref. */ |
557 | __drm_framebuffer_unregister(dev, fb); |
549 | __drm_framebuffer_unregister(dev, fb); |
Line 599... | Line 591... | ||
599 | * last reference to the framebuffer. It is also guaranteed to not take the |
591 | * last reference to the framebuffer. It is also guaranteed to not take the |
600 | * modeset locks in this case. |
592 | * modeset locks in this case. |
601 | */ |
593 | */ |
602 | void drm_framebuffer_remove(struct drm_framebuffer *fb) |
594 | void drm_framebuffer_remove(struct drm_framebuffer *fb) |
603 | { |
595 | { |
604 | struct drm_device *dev = fb->dev; |
596 | struct drm_device *dev; |
605 | struct drm_crtc *crtc; |
597 | struct drm_crtc *crtc; |
606 | struct drm_plane *plane; |
598 | struct drm_plane *plane; |
607 | struct drm_mode_set set; |
599 | struct drm_mode_set set; |
608 | int ret; |
600 | int ret; |
Line -... | Line 601... | ||
- | 601 | ||
- | 602 | if (!fb) |
|
- | 603 | return; |
|
- | 604 | ||
- | 605 | dev = fb->dev; |
|
609 | 606 | ||
Line 610... | Line 607... | ||
610 | WARN_ON(!list_empty(&fb->filp_head)); |
607 | WARN_ON(!list_empty(&fb->filp_head)); |
611 | 608 | ||
612 | /* |
609 | /* |
Line 625... | Line 622... | ||
625 | * in this manner. |
622 | * in this manner. |
626 | */ |
623 | */ |
627 | if (atomic_read(&fb->refcount.refcount) > 1) { |
624 | if (atomic_read(&fb->refcount.refcount) > 1) { |
628 | drm_modeset_lock_all(dev); |
625 | drm_modeset_lock_all(dev); |
629 | /* remove from any CRTC */ |
626 | /* remove from any CRTC */ |
630 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
627 | drm_for_each_crtc(crtc, dev) { |
631 | if (crtc->primary->fb == fb) { |
628 | if (crtc->primary->fb == fb) { |
632 | /* should turn off the crtc */ |
629 | /* should turn off the crtc */ |
633 | memset(&set, 0, sizeof(struct drm_mode_set)); |
630 | memset(&set, 0, sizeof(struct drm_mode_set)); |
634 | set.crtc = crtc; |
631 | set.crtc = crtc; |
635 | set.fb = NULL; |
632 | set.fb = NULL; |
Line 637... | Line 634... | ||
637 | if (ret) |
634 | if (ret) |
638 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); |
635 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); |
639 | } |
636 | } |
640 | } |
637 | } |
Line 641... | Line 638... | ||
641 | 638 | ||
642 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) { |
639 | drm_for_each_plane(plane, dev) { |
643 | if (plane->fb == fb) |
640 | if (plane->fb == fb) |
644 | drm_plane_force_disable(plane); |
641 | drm_plane_force_disable(plane); |
645 | } |
642 | } |
646 | drm_modeset_unlock_all(dev); |
643 | drm_modeset_unlock_all(dev); |
Line 672... | Line 669... | ||
672 | const struct drm_crtc_funcs *funcs) |
669 | const struct drm_crtc_funcs *funcs) |
673 | { |
670 | { |
674 | struct drm_mode_config *config = &dev->mode_config; |
671 | struct drm_mode_config *config = &dev->mode_config; |
675 | int ret; |
672 | int ret; |
Line -... | Line 673... | ||
- | 673 | ||
- | 674 | WARN_ON(primary && primary->type != DRM_PLANE_TYPE_PRIMARY); |
|
- | 675 | WARN_ON(cursor && cursor->type != DRM_PLANE_TYPE_CURSOR); |
|
676 | 676 | ||
677 | crtc->dev = dev; |
677 | crtc->dev = dev; |
678 | crtc->funcs = funcs; |
- | |
Line 679... | Line 678... | ||
679 | crtc->invert_dimensions = false; |
678 | crtc->funcs = funcs; |
680 | 679 | ||
681 | drm_modeset_lock_init(&crtc->mutex); |
680 | drm_modeset_lock_init(&crtc->mutex); |
682 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
681 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
Line 693... | Line 692... | ||
693 | if (primary) |
692 | if (primary) |
694 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); |
693 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); |
695 | if (cursor) |
694 | if (cursor) |
696 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
695 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
Line -... | Line 696... | ||
- | 696 | ||
- | 697 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { |
|
- | 698 | drm_object_attach_property(&crtc->base, config->prop_active, 0); |
|
- | 699 | drm_object_attach_property(&crtc->base, config->prop_mode_id, 0); |
|
- | 700 | } |
|
697 | 701 | ||
698 | return 0; |
702 | return 0; |
699 | } |
703 | } |
Line 700... | Line 704... | ||
700 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
704 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
Line 738... | Line 742... | ||
738 | unsigned int drm_crtc_index(struct drm_crtc *crtc) |
742 | unsigned int drm_crtc_index(struct drm_crtc *crtc) |
739 | { |
743 | { |
740 | unsigned int index = 0; |
744 | unsigned int index = 0; |
741 | struct drm_crtc *tmp; |
745 | struct drm_crtc *tmp; |
Line 742... | Line 746... | ||
742 | 746 | ||
743 | list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { |
747 | drm_for_each_crtc(tmp, crtc->dev) { |
744 | if (tmp == crtc) |
748 | if (tmp == crtc) |
Line 745... | Line 749... | ||
745 | return index; |
749 | return index; |
746 | 750 | ||
Line 764... | Line 768... | ||
764 | list_del(&mode->head); |
768 | list_del(&mode->head); |
765 | drm_mode_destroy(connector->dev, mode); |
769 | drm_mode_destroy(connector->dev, mode); |
766 | } |
770 | } |
Line 767... | Line 771... | ||
767 | 771 | ||
- | 772 | /** |
|
- | 773 | * drm_display_info_set_bus_formats - set the supported bus formats |
|
- | 774 | * @info: display info to store bus formats in |
|
- | 775 | * @formats: array containing the supported bus formats |
|
- | 776 | * @num_formats: the number of entries in the fmts array |
|
- | 777 | * |
|
- | 778 | * Store the supported bus formats in display info structure. |
|
- | 779 | * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for |
|
- | 780 | * a full list of available formats. |
|
- | 781 | */ |
|
- | 782 | int drm_display_info_set_bus_formats(struct drm_display_info *info, |
|
- | 783 | const u32 *formats, |
|
- | 784 | unsigned int num_formats) |
|
- | 785 | { |
|
- | 786 | u32 *fmts = NULL; |
|
- | 787 | ||
- | 788 | if (!formats && num_formats) |
|
- | 789 | return -EINVAL; |
|
- | 790 | ||
- | 791 | if (formats && num_formats) { |
|
- | 792 | fmts = kmemdup(formats, sizeof(*formats) * num_formats, |
|
- | 793 | GFP_KERNEL); |
|
- | 794 | if (!fmts) |
|
- | 795 | return -ENOMEM; |
|
- | 796 | } |
|
- | 797 | ||
- | 798 | kfree(info->bus_formats); |
|
- | 799 | info->bus_formats = fmts; |
|
- | 800 | info->num_bus_formats = num_formats; |
|
- | 801 | ||
- | 802 | return 0; |
|
- | 803 | } |
|
- | 804 | EXPORT_SYMBOL(drm_display_info_set_bus_formats); |
|
- | 805 | ||
- | 806 | /** |
|
- | 807 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode |
|
- | 808 | * @connector: connector to quwery |
|
- | 809 | * |
|
- | 810 | * The kernel supports per-connector configration of its consoles through |
|
- | 811 | * use of the video= parameter. This function parses that option and |
|
- | 812 | * extracts the user's specified mode (or enable/disable status) for a |
|
- | 813 | * particular connector. This is typically only used during the early fbdev |
|
- | 814 | * setup. |
|
- | 815 | */ |
|
- | 816 | static void drm_connector_get_cmdline_mode(struct drm_connector *connector) |
|
- | 817 | { |
|
- | 818 | struct drm_cmdline_mode *mode = &connector->cmdline_mode; |
|
- | 819 | char *option = NULL; |
|
- | 820 | ||
- | 821 | return; |
|
- | 822 | #if 0 |
|
- | 823 | if (fb_get_options(connector->name, &option)) |
|
- | 824 | return; |
|
- | 825 | ||
- | 826 | if (!drm_mode_parse_command_line_for_connector(option, |
|
- | 827 | connector, |
|
- | 828 | mode)) |
|
- | 829 | return; |
|
- | 830 | ||
- | 831 | if (mode->force) { |
|
- | 832 | const char *s; |
|
- | 833 | ||
- | 834 | switch (mode->force) { |
|
- | 835 | case DRM_FORCE_OFF: |
|
- | 836 | s = "OFF"; |
|
- | 837 | break; |
|
- | 838 | case DRM_FORCE_ON_DIGITAL: |
|
- | 839 | s = "ON - dig"; |
|
- | 840 | break; |
|
- | 841 | default: |
|
- | 842 | case DRM_FORCE_ON: |
|
- | 843 | s = "ON"; |
|
- | 844 | break; |
|
- | 845 | } |
|
- | 846 | ||
- | 847 | DRM_INFO("forcing %s connector %s\n", connector->name, s); |
|
- | 848 | connector->force = mode->force; |
|
- | 849 | } |
|
- | 850 | ||
- | 851 | DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n", |
|
- | 852 | connector->name, |
|
- | 853 | mode->xres, mode->yres, |
|
- | 854 | mode->refresh_specified ? mode->refresh : 60, |
|
- | 855 | mode->rb ? " reduced blanking" : "", |
|
- | 856 | mode->margins ? " with margins" : "", |
|
- | 857 | mode->interlace ? " interlaced" : ""); |
|
- | 858 | #endif |
|
- | 859 | } |
|
- | 860 | ||
768 | /** |
861 | /** |
769 | * drm_connector_init - Init a preallocated connector |
862 | * drm_connector_init - Init a preallocated connector |
770 | * @dev: DRM device |
863 | * @dev: DRM device |
771 | * @connector: the connector to init |
864 | * @connector: the connector to init |
772 | * @funcs: callbacks for this connector |
865 | * @funcs: callbacks for this connector |
Line 781... | Line 874... | ||
781 | int drm_connector_init(struct drm_device *dev, |
874 | int drm_connector_init(struct drm_device *dev, |
782 | struct drm_connector *connector, |
875 | struct drm_connector *connector, |
783 | const struct drm_connector_funcs *funcs, |
876 | const struct drm_connector_funcs *funcs, |
784 | int connector_type) |
877 | int connector_type) |
785 | { |
878 | { |
- | 879 | struct drm_mode_config *config = &dev->mode_config; |
|
786 | int ret; |
880 | int ret; |
787 | struct ida *connector_ida = |
881 | struct ida *connector_ida = |
788 | &drm_connector_enum_list[connector_type].ida; |
882 | &drm_connector_enum_list[connector_type].ida; |
Line 789... | Line 883... | ||
789 | 883 | ||
Line 815... | Line 909... | ||
815 | INIT_LIST_HEAD(&connector->probed_modes); |
909 | INIT_LIST_HEAD(&connector->probed_modes); |
816 | INIT_LIST_HEAD(&connector->modes); |
910 | INIT_LIST_HEAD(&connector->modes); |
817 | connector->edid_blob_ptr = NULL; |
911 | connector->edid_blob_ptr = NULL; |
818 | connector->status = connector_status_unknown; |
912 | connector->status = connector_status_unknown; |
Line -... | Line 913... | ||
- | 913 | ||
- | 914 | drm_connector_get_cmdline_mode(connector); |
|
- | 915 | ||
- | 916 | /* We should add connectors at the end to avoid upsetting the connector |
|
819 | 917 | * index too much. */ |
|
820 | list_add_tail(&connector->head, &dev->mode_config.connector_list); |
918 | list_add_tail(&connector->head, &config->connector_list); |
Line 821... | Line 919... | ||
821 | dev->mode_config.num_connector++; |
919 | config->num_connector++; |
822 | 920 | ||
823 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) |
921 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) |
824 | drm_object_attach_property(&connector->base, |
922 | drm_object_attach_property(&connector->base, |
Line 825... | Line 923... | ||
825 | dev->mode_config.edid_property, |
923 | config->edid_property, |
826 | 0); |
924 | 0); |
- | 925 | ||
- | 926 | drm_object_attach_property(&connector->base, |
|
- | 927 | config->dpms_property, 0); |
|
- | 928 | ||
Line 827... | Line 929... | ||
827 | 929 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { |
|
Line 828... | Line 930... | ||
828 | drm_object_attach_property(&connector->base, |
930 | drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); |
829 | dev->mode_config.dpms_property, 0); |
931 | } |
Line 850... | Line 952... | ||
850 | void drm_connector_cleanup(struct drm_connector *connector) |
952 | void drm_connector_cleanup(struct drm_connector *connector) |
851 | { |
953 | { |
852 | struct drm_device *dev = connector->dev; |
954 | struct drm_device *dev = connector->dev; |
853 | struct drm_display_mode *mode, *t; |
955 | struct drm_display_mode *mode, *t; |
Line -... | Line 956... | ||
- | 956 | ||
- | 957 | if (connector->tile_group) { |
|
- | 958 | drm_mode_put_tile_group(dev, connector->tile_group); |
|
- | 959 | connector->tile_group = NULL; |
|
- | 960 | } |
|
854 | 961 | ||
855 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) |
962 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) |
Line 856... | Line 963... | ||
856 | drm_mode_remove(connector, mode); |
963 | drm_mode_remove(connector, mode); |
857 | 964 | ||
Line 858... | Line 965... | ||
858 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
965 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
859 | drm_mode_remove(connector, mode); |
966 | drm_mode_remove(connector, mode); |
Line -... | Line 967... | ||
- | 967 | ||
860 | 968 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, |
|
861 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, |
969 | connector->connector_type_id); |
862 | connector->connector_type_id); |
970 | |
863 | 971 | kfree(connector->display_info.bus_formats); |
|
864 | drm_mode_object_put(dev, &connector->base); |
972 | drm_mode_object_put(dev, &connector->base); |
Line 889... | Line 997... | ||
889 | struct drm_connector *tmp; |
997 | struct drm_connector *tmp; |
890 | struct drm_mode_config *config = &connector->dev->mode_config; |
998 | struct drm_mode_config *config = &connector->dev->mode_config; |
Line 891... | Line 999... | ||
891 | 999 | ||
Line 892... | Line 1000... | ||
892 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); |
1000 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); |
893 | 1001 | ||
894 | list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) { |
1002 | drm_for_each_connector(tmp, connector->dev) { |
Line 895... | Line 1003... | ||
895 | if (tmp == connector) |
1003 | if (tmp == connector) |
896 | return index; |
1004 | return index; |
Line 915... | Line 1023... | ||
915 | { |
1023 | { |
916 | int ret; |
1024 | int ret; |
Line 917... | Line 1025... | ||
917 | 1025 | ||
Line -... | Line 1026... | ||
- | 1026 | drm_mode_object_register(connector->dev, &connector->base); |
|
- | 1027 | ||
- | 1028 | ret = drm_sysfs_connector_add(connector); |
|
918 | drm_mode_object_register(connector->dev, &connector->base); |
1029 | if (ret) |
919 | 1030 | return ret; |
|
920 | return 0; |
1031 | return 0; |
Line 921... | Line 1032... | ||
921 | } |
1032 | } |
Line 927... | Line 1038... | ||
927 | * |
1038 | * |
928 | * Unregister userspace interfaces for a connector |
1039 | * Unregister userspace interfaces for a connector |
929 | */ |
1040 | */ |
930 | void drm_connector_unregister(struct drm_connector *connector) |
1041 | void drm_connector_unregister(struct drm_connector *connector) |
931 | { |
1042 | { |
- | 1043 | drm_sysfs_connector_remove(connector); |
|
932 | } |
1044 | } |
933 | EXPORT_SYMBOL(drm_connector_unregister); |
1045 | EXPORT_SYMBOL(drm_connector_unregister); |
Line 934... | Line 1046... | ||
934 | 1046 | ||
Line 943... | Line 1055... | ||
943 | */ |
1055 | */ |
944 | void drm_connector_unplug_all(struct drm_device *dev) |
1056 | void drm_connector_unplug_all(struct drm_device *dev) |
945 | { |
1057 | { |
946 | struct drm_connector *connector; |
1058 | struct drm_connector *connector; |
Line 947... | Line 1059... | ||
947 | 1059 | ||
948 | /* taking the mode config mutex ends up in a clash with sysfs */ |
1060 | /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ |
949 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
1061 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
Line 950... | Line 1062... | ||
950 | drm_connector_unregister(connector); |
1062 | drm_connector_unregister(connector); |
951 | 1063 | ||
Line 952... | Line 1064... | ||
952 | } |
1064 | } |
953 | EXPORT_SYMBOL(drm_connector_unplug_all); |
- | |
954 | - | ||
955 | /** |
- | |
956 | * drm_bridge_init - initialize a drm transcoder/bridge |
- | |
957 | * @dev: drm device |
- | |
958 | * @bridge: transcoder/bridge to set up |
- | |
959 | * @funcs: bridge function table |
- | |
960 | * |
- | |
961 | * Initialises a preallocated bridge. Bridges should be |
- | |
962 | * subclassed as part of driver connector objects. |
- | |
963 | * |
- | |
964 | * Returns: |
- | |
965 | * Zero on success, error code on failure. |
- | |
966 | */ |
- | |
967 | int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge, |
- | |
968 | const struct drm_bridge_funcs *funcs) |
- | |
969 | { |
- | |
970 | int ret; |
- | |
971 | - | ||
972 | drm_modeset_lock_all(dev); |
- | |
973 | - | ||
974 | ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE); |
- | |
975 | if (ret) |
- | |
976 | goto out; |
- | |
977 | - | ||
978 | bridge->dev = dev; |
- | |
979 | bridge->funcs = funcs; |
- | |
980 | - | ||
981 | list_add_tail(&bridge->head, &dev->mode_config.bridge_list); |
- | |
982 | dev->mode_config.num_bridge++; |
- | |
983 | - | ||
984 | out: |
- | |
985 | drm_modeset_unlock_all(dev); |
- | |
986 | return ret; |
- | |
987 | } |
- | |
988 | EXPORT_SYMBOL(drm_bridge_init); |
- | |
989 | - | ||
990 | /** |
- | |
991 | * drm_bridge_cleanup - cleans up an initialised bridge |
- | |
992 | * @bridge: bridge to cleanup |
- | |
993 | * |
- | |
994 | * Cleans up the bridge but doesn't free the object. |
- | |
995 | */ |
- | |
996 | void drm_bridge_cleanup(struct drm_bridge *bridge) |
- | |
997 | { |
- | |
998 | struct drm_device *dev = bridge->dev; |
- | |
999 | - | ||
1000 | drm_modeset_lock_all(dev); |
- | |
1001 | drm_mode_object_put(dev, &bridge->base); |
- | |
1002 | list_del(&bridge->head); |
- | |
1003 | dev->mode_config.num_bridge--; |
- | |
1004 | drm_modeset_unlock_all(dev); |
- | |
1005 | - | ||
1006 | memset(bridge, 0, sizeof(*bridge)); |
- | |
1007 | } |
- | |
1008 | EXPORT_SYMBOL(drm_bridge_cleanup); |
1065 | EXPORT_SYMBOL(drm_connector_unplug_all); |
1009 | 1066 | ||
1010 | /** |
1067 | /** |
1011 | * drm_encoder_init - Init a preallocated encoder |
1068 | * drm_encoder_init - Init a preallocated encoder |
1012 | * @dev: drm device |
1069 | * @dev: drm device |
Line 1065... | Line 1122... | ||
1065 | * Cleans up the encoder but doesn't free the object. |
1122 | * Cleans up the encoder but doesn't free the object. |
1066 | */ |
1123 | */ |
1067 | void drm_encoder_cleanup(struct drm_encoder *encoder) |
1124 | void drm_encoder_cleanup(struct drm_encoder *encoder) |
1068 | { |
1125 | { |
1069 | struct drm_device *dev = encoder->dev; |
1126 | struct drm_device *dev = encoder->dev; |
- | 1127 | ||
1070 | drm_modeset_lock_all(dev); |
1128 | drm_modeset_lock_all(dev); |
1071 | drm_mode_object_put(dev, &encoder->base); |
1129 | drm_mode_object_put(dev, &encoder->base); |
1072 | kfree(encoder->name); |
1130 | kfree(encoder->name); |
1073 | list_del(&encoder->head); |
1131 | list_del(&encoder->head); |
1074 | dev->mode_config.num_encoder--; |
1132 | dev->mode_config.num_encoder--; |
Line 1094... | Line 1152... | ||
1094 | * Zero on success, error code on failure. |
1152 | * Zero on success, error code on failure. |
1095 | */ |
1153 | */ |
1096 | int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, |
1154 | int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, |
1097 | unsigned long possible_crtcs, |
1155 | unsigned long possible_crtcs, |
1098 | const struct drm_plane_funcs *funcs, |
1156 | const struct drm_plane_funcs *funcs, |
1099 | const uint32_t *formats, uint32_t format_count, |
1157 | const uint32_t *formats, unsigned int format_count, |
1100 | enum drm_plane_type type) |
1158 | enum drm_plane_type type) |
1101 | { |
1159 | { |
- | 1160 | struct drm_mode_config *config = &dev->mode_config; |
|
1102 | int ret; |
1161 | int ret; |
Line 1103... | Line 1162... | ||
1103 | 1162 | ||
1104 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
1163 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
1105 | if (ret) |
1164 | if (ret) |
Line 1108... | Line 1167... | ||
1108 | drm_modeset_lock_init(&plane->mutex); |
1167 | drm_modeset_lock_init(&plane->mutex); |
Line 1109... | Line 1168... | ||
1109 | 1168 | ||
1110 | plane->base.properties = &plane->properties; |
1169 | plane->base.properties = &plane->properties; |
1111 | plane->dev = dev; |
1170 | plane->dev = dev; |
1112 | plane->funcs = funcs; |
1171 | plane->funcs = funcs; |
1113 | plane->format_types = kmalloc(sizeof(uint32_t) * format_count, |
1172 | plane->format_types = kmalloc_array(format_count, sizeof(uint32_t), |
1114 | GFP_KERNEL); |
1173 | GFP_KERNEL); |
1115 | if (!plane->format_types) { |
1174 | if (!plane->format_types) { |
1116 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1175 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1117 | drm_mode_object_put(dev, &plane->base); |
1176 | drm_mode_object_put(dev, &plane->base); |
Line 1121... | Line 1180... | ||
1121 | memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); |
1180 | memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); |
1122 | plane->format_count = format_count; |
1181 | plane->format_count = format_count; |
1123 | plane->possible_crtcs = possible_crtcs; |
1182 | plane->possible_crtcs = possible_crtcs; |
1124 | plane->type = type; |
1183 | plane->type = type; |
Line 1125... | Line 1184... | ||
1125 | 1184 | ||
1126 | list_add_tail(&plane->head, &dev->mode_config.plane_list); |
1185 | list_add_tail(&plane->head, &config->plane_list); |
1127 | dev->mode_config.num_total_plane++; |
1186 | config->num_total_plane++; |
1128 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1187 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
Line 1129... | Line 1188... | ||
1129 | dev->mode_config.num_overlay_plane++; |
1188 | config->num_overlay_plane++; |
1130 | 1189 | ||
1131 | drm_object_attach_property(&plane->base, |
1190 | drm_object_attach_property(&plane->base, |
Line -... | Line 1191... | ||
- | 1191 | config->plane_type_property, |
|
- | 1192 | plane->type); |
|
- | 1193 | ||
- | 1194 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { |
|
- | 1195 | drm_object_attach_property(&plane->base, config->prop_fb_id, 0); |
|
- | 1196 | drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); |
|
- | 1197 | drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); |
|
- | 1198 | drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); |
|
- | 1199 | drm_object_attach_property(&plane->base, config->prop_crtc_w, 0); |
|
- | 1200 | drm_object_attach_property(&plane->base, config->prop_crtc_h, 0); |
|
- | 1201 | drm_object_attach_property(&plane->base, config->prop_src_x, 0); |
|
- | 1202 | drm_object_attach_property(&plane->base, config->prop_src_y, 0); |
|
- | 1203 | drm_object_attach_property(&plane->base, config->prop_src_w, 0); |
|
1132 | dev->mode_config.plane_type_property, |
1204 | drm_object_attach_property(&plane->base, config->prop_src_h, 0); |
1133 | plane->type); |
1205 | } |
1134 | 1206 | ||
Line 1135... | Line 1207... | ||
1135 | return 0; |
1207 | return 0; |
Line 1154... | Line 1226... | ||
1154 | * Zero on success, error code on failure. |
1226 | * Zero on success, error code on failure. |
1155 | */ |
1227 | */ |
1156 | int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, |
1228 | int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, |
1157 | unsigned long possible_crtcs, |
1229 | unsigned long possible_crtcs, |
1158 | const struct drm_plane_funcs *funcs, |
1230 | const struct drm_plane_funcs *funcs, |
1159 | const uint32_t *formats, uint32_t format_count, |
1231 | const uint32_t *formats, unsigned int format_count, |
1160 | bool is_primary) |
1232 | bool is_primary) |
1161 | { |
1233 | { |
1162 | enum drm_plane_type type; |
1234 | enum drm_plane_type type; |
Line 1163... | Line 1235... | ||
1163 | 1235 | ||
Line 1209... | Line 1281... | ||
1209 | unsigned int drm_plane_index(struct drm_plane *plane) |
1281 | unsigned int drm_plane_index(struct drm_plane *plane) |
1210 | { |
1282 | { |
1211 | unsigned int index = 0; |
1283 | unsigned int index = 0; |
1212 | struct drm_plane *tmp; |
1284 | struct drm_plane *tmp; |
Line 1213... | Line 1285... | ||
1213 | 1285 | ||
1214 | list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) { |
1286 | drm_for_each_plane(tmp, plane->dev) { |
1215 | if (tmp == plane) |
1287 | if (tmp == plane) |
Line 1216... | Line 1288... | ||
1216 | return index; |
1288 | return index; |
1217 | 1289 | ||
Line 1221... | Line 1293... | ||
1221 | BUG(); |
1293 | BUG(); |
1222 | } |
1294 | } |
1223 | EXPORT_SYMBOL(drm_plane_index); |
1295 | EXPORT_SYMBOL(drm_plane_index); |
Line 1224... | Line 1296... | ||
1224 | 1296 | ||
- | 1297 | /** |
|
- | 1298 | * drm_plane_from_index - find the registered plane at an index |
|
- | 1299 | * @dev: DRM device |
|
- | 1300 | * @idx: index of registered plane to find for |
|
- | 1301 | * |
|
- | 1302 | * Given a plane index, return the registered plane from DRM device's |
|
- | 1303 | * list of planes with matching index. |
|
- | 1304 | */ |
|
- | 1305 | struct drm_plane * |
|
- | 1306 | drm_plane_from_index(struct drm_device *dev, int idx) |
|
- | 1307 | { |
|
- | 1308 | struct drm_plane *plane; |
|
- | 1309 | unsigned int i = 0; |
|
- | 1310 | ||
- | 1311 | drm_for_each_plane(plane, dev) { |
|
- | 1312 | if (i == idx) |
|
- | 1313 | return plane; |
|
- | 1314 | i++; |
|
- | 1315 | } |
|
- | 1316 | return NULL; |
|
- | 1317 | } |
|
- | 1318 | EXPORT_SYMBOL(drm_plane_from_index); |
|
- | 1319 | ||
1225 | /** |
1320 | /** |
1226 | * drm_plane_force_disable - Forcibly disable a plane |
1321 | * drm_plane_force_disable - Forcibly disable a plane |
1227 | * @plane: plane to disable |
1322 | * @plane: plane to disable |
1228 | * |
1323 | * |
1229 | * Forces the plane to be disabled. |
1324 | * Forces the plane to be disabled. |
Line 1244... | Line 1339... | ||
1244 | DRM_ERROR("failed to disable plane with busy fb\n"); |
1339 | DRM_ERROR("failed to disable plane with busy fb\n"); |
1245 | plane->old_fb = NULL; |
1340 | plane->old_fb = NULL; |
1246 | return; |
1341 | return; |
1247 | } |
1342 | } |
1248 | /* disconnect the plane from the fb and crtc: */ |
1343 | /* disconnect the plane from the fb and crtc: */ |
1249 | __drm_framebuffer_unreference(plane->old_fb); |
1344 | drm_framebuffer_unreference(plane->old_fb); |
1250 | plane->old_fb = NULL; |
1345 | plane->old_fb = NULL; |
1251 | plane->fb = NULL; |
1346 | plane->fb = NULL; |
1252 | plane->crtc = NULL; |
1347 | plane->crtc = NULL; |
1253 | } |
1348 | } |
1254 | EXPORT_SYMBOL(drm_plane_force_disable); |
1349 | EXPORT_SYMBOL(drm_plane_force_disable); |
Line 1255... | Line 1350... | ||
1255 | 1350 | ||
1256 | static int drm_mode_create_standard_connector_properties(struct drm_device *dev) |
1351 | static int drm_mode_create_standard_properties(struct drm_device *dev) |
1257 | { |
- | |
1258 | struct drm_property *edid; |
1352 | { |
1259 | struct drm_property *dpms; |
- | |
Line 1260... | Line 1353... | ||
1260 | struct drm_property *dev_path; |
1353 | struct drm_property *prop; |
1261 | 1354 | ||
1262 | /* |
1355 | /* |
1263 | * Standard properties (apply to all connectors) |
1356 | * Standard properties (apply to all connectors) |
1264 | */ |
1357 | */ |
1265 | edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | |
1358 | prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | |
- | 1359 | DRM_MODE_PROP_IMMUTABLE, |
|
- | 1360 | "EDID", 0); |
|
1266 | DRM_MODE_PROP_IMMUTABLE, |
1361 | if (!prop) |
Line 1267... | Line 1362... | ||
1267 | "EDID", 0); |
1362 | return -ENOMEM; |
1268 | dev->mode_config.edid_property = edid; |
1363 | dev->mode_config.edid_property = prop; |
1269 | 1364 | ||
- | 1365 | prop = drm_property_create_enum(dev, 0, |
|
- | 1366 | "DPMS", drm_dpms_enum_list, |
|
1270 | dpms = drm_property_create_enum(dev, 0, |
1367 | ARRAY_SIZE(drm_dpms_enum_list)); |
Line 1271... | Line 1368... | ||
1271 | "DPMS", drm_dpms_enum_list, |
1368 | if (!prop) |
1272 | ARRAY_SIZE(drm_dpms_enum_list)); |
1369 | return -ENOMEM; |
1273 | dev->mode_config.dpms_property = dpms; |
1370 | dev->mode_config.dpms_property = prop; |
1274 | 1371 | ||
- | 1372 | prop = drm_property_create(dev, |
|
- | 1373 | DRM_MODE_PROP_BLOB | |
|
1275 | dev_path = drm_property_create(dev, |
1374 | DRM_MODE_PROP_IMMUTABLE, |
Line 1276... | Line 1375... | ||
1276 | DRM_MODE_PROP_BLOB | |
1375 | "PATH", 0); |
1277 | DRM_MODE_PROP_IMMUTABLE, |
1376 | if (!prop) |
1278 | "PATH", 0); |
1377 | return -ENOMEM; |
1279 | dev->mode_config.path_property = dev_path; |
1378 | dev->mode_config.path_property = prop; |
- | 1379 | ||
- | 1380 | prop = drm_property_create(dev, |
|
- | 1381 | DRM_MODE_PROP_BLOB | |
|
Line 1280... | Line -... | ||
1280 | - | ||
1281 | dev->mode_config.tile_property = drm_property_create(dev, |
- | |
1282 | DRM_MODE_PROP_BLOB | |
- | |
1283 | DRM_MODE_PROP_IMMUTABLE, |
- | |
1284 | "TILE", 0); |
- | |
1285 | - | ||
1286 | return 0; |
- | |
1287 | } |
- | |
1288 | - | ||
1289 | static int drm_mode_create_standard_plane_properties(struct drm_device *dev) |
- | |
1290 | { |
1382 | DRM_MODE_PROP_IMMUTABLE, |
1291 | struct drm_property *type; |
1383 | "TILE", 0); |
1292 | 1384 | if (!prop) |
|
- | 1385 | return -ENOMEM; |
|
- | 1386 | dev->mode_config.tile_property = prop; |
|
1293 | /* |
1387 | |
- | 1388 | prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
|
- | 1389 | "type", drm_plane_type_enum_list, |
|
- | 1390 | ARRAY_SIZE(drm_plane_type_enum_list)); |
|
- | 1391 | if (!prop) |
|
- | 1392 | return -ENOMEM; |
|
- | 1393 | dev->mode_config.plane_type_property = prop; |
|
- | 1394 | ||
- | 1395 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1396 | "SRC_X", 0, UINT_MAX); |
|
- | 1397 | if (!prop) |
|
- | 1398 | return -ENOMEM; |
|
- | 1399 | dev->mode_config.prop_src_x = prop; |
|
- | 1400 | ||
- | 1401 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1402 | "SRC_Y", 0, UINT_MAX); |
|
- | 1403 | if (!prop) |
|
- | 1404 | return -ENOMEM; |
|
- | 1405 | dev->mode_config.prop_src_y = prop; |
|
- | 1406 | ||
- | 1407 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1408 | "SRC_W", 0, UINT_MAX); |
|
- | 1409 | if (!prop) |
|
- | 1410 | return -ENOMEM; |
|
- | 1411 | dev->mode_config.prop_src_w = prop; |
|
- | 1412 | ||
- | 1413 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1414 | "SRC_H", 0, UINT_MAX); |
|
- | 1415 | if (!prop) |
|
- | 1416 | return -ENOMEM; |
|
- | 1417 | dev->mode_config.prop_src_h = prop; |
|
- | 1418 | ||
- | 1419 | prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1420 | "CRTC_X", INT_MIN, INT_MAX); |
|
- | 1421 | if (!prop) |
|
- | 1422 | return -ENOMEM; |
|
- | 1423 | dev->mode_config.prop_crtc_x = prop; |
|
- | 1424 | ||
- | 1425 | prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1426 | "CRTC_Y", INT_MIN, INT_MAX); |
|
- | 1427 | if (!prop) |
|
- | 1428 | return -ENOMEM; |
|
- | 1429 | dev->mode_config.prop_crtc_y = prop; |
|
- | 1430 | ||
- | 1431 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1432 | "CRTC_W", 0, INT_MAX); |
|
- | 1433 | if (!prop) |
|
- | 1434 | return -ENOMEM; |
|
- | 1435 | dev->mode_config.prop_crtc_w = prop; |
|
- | 1436 | ||
- | 1437 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1438 | "CRTC_H", 0, INT_MAX); |
|
- | 1439 | if (!prop) |
|
- | 1440 | return -ENOMEM; |
|
- | 1441 | dev->mode_config.prop_crtc_h = prop; |
|
- | 1442 | ||
- | 1443 | prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1444 | "FB_ID", DRM_MODE_OBJECT_FB); |
|
- | 1445 | if (!prop) |
|
- | 1446 | return -ENOMEM; |
|
- | 1447 | dev->mode_config.prop_fb_id = prop; |
|
- | 1448 | ||
- | 1449 | prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1450 | "CRTC_ID", DRM_MODE_OBJECT_CRTC); |
|
- | 1451 | if (!prop) |
|
- | 1452 | return -ENOMEM; |
|
- | 1453 | dev->mode_config.prop_crtc_id = prop; |
|
- | 1454 | ||
- | 1455 | prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC, |
|
- | 1456 | "ACTIVE"); |
|
- | 1457 | if (!prop) |
|
- | 1458 | return -ENOMEM; |
|
- | 1459 | dev->mode_config.prop_active = prop; |
|
- | 1460 | ||
Line 1294... | Line 1461... | ||
1294 | * Standard properties (apply to all planes) |
1461 | prop = drm_property_create(dev, |
1295 | */ |
1462 | DRM_MODE_PROP_ATOMIC | DRM_MODE_PROP_BLOB, |
Line 1296... | Line 1463... | ||
1296 | type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
1463 | "MODE_ID", 0); |
Line 1343... | Line 1510... | ||
1343 | * responsible for allocating a list of format names and passing them to |
1510 | * responsible for allocating a list of format names and passing them to |
1344 | * this routine. |
1511 | * this routine. |
1345 | */ |
1512 | */ |
1346 | int drm_mode_create_tv_properties(struct drm_device *dev, |
1513 | int drm_mode_create_tv_properties(struct drm_device *dev, |
1347 | unsigned int num_modes, |
1514 | unsigned int num_modes, |
1348 | char *modes[]) |
1515 | const char * const modes[]) |
1349 | { |
1516 | { |
1350 | struct drm_property *tv_selector; |
1517 | struct drm_property *tv_selector; |
1351 | struct drm_property *tv_subconnector; |
1518 | struct drm_property *tv_subconnector; |
1352 | unsigned int i; |
1519 | unsigned int i; |
Line 1359... | Line 1526... | ||
1359 | */ |
1526 | */ |
1360 | tv_selector = drm_property_create_enum(dev, 0, |
1527 | tv_selector = drm_property_create_enum(dev, 0, |
1361 | "select subconnector", |
1528 | "select subconnector", |
1362 | drm_tv_select_enum_list, |
1529 | drm_tv_select_enum_list, |
1363 | ARRAY_SIZE(drm_tv_select_enum_list)); |
1530 | ARRAY_SIZE(drm_tv_select_enum_list)); |
- | 1531 | if (!tv_selector) |
|
- | 1532 | goto nomem; |
|
- | 1533 | ||
1364 | dev->mode_config.tv_select_subconnector_property = tv_selector; |
1534 | dev->mode_config.tv_select_subconnector_property = tv_selector; |
Line 1365... | Line 1535... | ||
1365 | 1535 | ||
1366 | tv_subconnector = |
1536 | tv_subconnector = |
1367 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
1537 | drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
1368 | "subconnector", |
1538 | "subconnector", |
1369 | drm_tv_subconnector_enum_list, |
1539 | drm_tv_subconnector_enum_list, |
- | 1540 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); |
|
- | 1541 | if (!tv_subconnector) |
|
1370 | ARRAY_SIZE(drm_tv_subconnector_enum_list)); |
1542 | goto nomem; |
Line 1371... | Line 1543... | ||
1371 | dev->mode_config.tv_subconnector_property = tv_subconnector; |
1543 | dev->mode_config.tv_subconnector_property = tv_subconnector; |
1372 | 1544 | ||
1373 | /* |
1545 | /* |
1374 | * Other, TV specific properties: margins & TV modes. |
1546 | * Other, TV specific properties: margins & TV modes. |
1375 | */ |
1547 | */ |
- | 1548 | dev->mode_config.tv_left_margin_property = |
|
- | 1549 | drm_property_create_range(dev, 0, "left margin", 0, 100); |
|
Line 1376... | Line 1550... | ||
1376 | dev->mode_config.tv_left_margin_property = |
1550 | if (!dev->mode_config.tv_left_margin_property) |
1377 | drm_property_create_range(dev, 0, "left margin", 0, 100); |
1551 | goto nomem; |
- | 1552 | ||
- | 1553 | dev->mode_config.tv_right_margin_property = |
|
Line 1378... | Line 1554... | ||
1378 | 1554 | drm_property_create_range(dev, 0, "right margin", 0, 100); |
|
1379 | dev->mode_config.tv_right_margin_property = |
1555 | if (!dev->mode_config.tv_right_margin_property) |
- | 1556 | goto nomem; |
|
- | 1557 | ||
Line 1380... | Line 1558... | ||
1380 | drm_property_create_range(dev, 0, "right margin", 0, 100); |
1558 | dev->mode_config.tv_top_margin_property = |
1381 | 1559 | drm_property_create_range(dev, 0, "top margin", 0, 100); |
|
- | 1560 | if (!dev->mode_config.tv_top_margin_property) |
|
- | 1561 | goto nomem; |
|
Line 1382... | Line 1562... | ||
1382 | dev->mode_config.tv_top_margin_property = |
1562 | |
1383 | drm_property_create_range(dev, 0, "top margin", 0, 100); |
1563 | dev->mode_config.tv_bottom_margin_property = |
1384 | 1564 | drm_property_create_range(dev, 0, "bottom margin", 0, 100); |
|
- | 1565 | if (!dev->mode_config.tv_bottom_margin_property) |
|
- | 1566 | goto nomem; |
|
- | 1567 | ||
1385 | dev->mode_config.tv_bottom_margin_property = |
1568 | dev->mode_config.tv_mode_property = |
1386 | drm_property_create_range(dev, 0, "bottom margin", 0, 100); |
1569 | drm_property_create(dev, DRM_MODE_PROP_ENUM, |
1387 | 1570 | "mode", num_modes); |
|
Line 1388... | Line 1571... | ||
1388 | dev->mode_config.tv_mode_property = |
1571 | if (!dev->mode_config.tv_mode_property) |
1389 | drm_property_create(dev, DRM_MODE_PROP_ENUM, |
1572 | goto nomem; |
- | 1573 | ||
- | 1574 | for (i = 0; i < num_modes; i++) |
|
Line 1390... | Line 1575... | ||
1390 | "mode", num_modes); |
1575 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, |
1391 | for (i = 0; i < num_modes; i++) |
1576 | i, modes[i]); |
- | 1577 | ||
- | 1578 | dev->mode_config.tv_brightness_property = |
|
Line 1392... | Line 1579... | ||
1392 | drm_property_add_enum(dev->mode_config.tv_mode_property, i, |
1579 | drm_property_create_range(dev, 0, "brightness", 0, 100); |
1393 | i, modes[i]); |
1580 | if (!dev->mode_config.tv_brightness_property) |
- | 1581 | goto nomem; |
|
- | 1582 | ||
Line 1394... | Line 1583... | ||
1394 | 1583 | dev->mode_config.tv_contrast_property = |
|
1395 | dev->mode_config.tv_brightness_property = |
1584 | drm_property_create_range(dev, 0, "contrast", 0, 100); |
- | 1585 | if (!dev->mode_config.tv_contrast_property) |
|
- | 1586 | goto nomem; |
|
Line 1396... | Line 1587... | ||
1396 | drm_property_create_range(dev, 0, "brightness", 0, 100); |
1587 | |
1397 | 1588 | dev->mode_config.tv_flicker_reduction_property = |
|
- | 1589 | drm_property_create_range(dev, 0, "flicker reduction", 0, 100); |
|
- | 1590 | if (!dev->mode_config.tv_flicker_reduction_property) |
|
Line 1398... | Line 1591... | ||
1398 | dev->mode_config.tv_contrast_property = |
1591 | goto nomem; |
1399 | drm_property_create_range(dev, 0, "contrast", 0, 100); |
1592 | |
- | 1593 | dev->mode_config.tv_overscan_property = |
|
- | 1594 | drm_property_create_range(dev, 0, "overscan", 0, 100); |
|
Line 1400... | Line 1595... | ||
1400 | 1595 | if (!dev->mode_config.tv_overscan_property) |
|
- | 1596 | goto nomem; |
|
- | 1597 | ||
1401 | dev->mode_config.tv_flicker_reduction_property = |
1598 | dev->mode_config.tv_saturation_property = |
1402 | drm_property_create_range(dev, 0, "flicker reduction", 0, 100); |
1599 | drm_property_create_range(dev, 0, "saturation", 0, 100); |
Line 1403... | Line 1600... | ||
1403 | 1600 | if (!dev->mode_config.tv_saturation_property) |
|
1404 | dev->mode_config.tv_overscan_property = |
1601 | goto nomem; |
Line 1513... | Line 1710... | ||
1513 | return -ENOMEM; |
1710 | return -ENOMEM; |
1514 | return 0; |
1711 | return 0; |
1515 | } |
1712 | } |
1516 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); |
1713 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); |
Line 1517... | Line -... | ||
1517 | - | ||
1518 | static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) |
- | |
1519 | { |
- | |
1520 | uint32_t total_objects = 0; |
- | |
1521 | - | ||
1522 | total_objects += dev->mode_config.num_crtc; |
- | |
1523 | total_objects += dev->mode_config.num_connector; |
- | |
1524 | total_objects += dev->mode_config.num_encoder; |
- | |
1525 | total_objects += dev->mode_config.num_bridge; |
- | |
1526 | - | ||
1527 | group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); |
- | |
1528 | if (!group->id_list) |
- | |
1529 | return -ENOMEM; |
- | |
1530 | - | ||
1531 | group->num_crtcs = 0; |
- | |
1532 | group->num_connectors = 0; |
- | |
1533 | group->num_encoders = 0; |
- | |
1534 | group->num_bridges = 0; |
- | |
1535 | return 0; |
- | |
1536 | } |
- | |
1537 | - | ||
1538 | void drm_mode_group_destroy(struct drm_mode_group *group) |
- | |
1539 | { |
- | |
1540 | kfree(group->id_list); |
- | |
1541 | group->id_list = NULL; |
- | |
1542 | } |
- | |
1543 | - | ||
1544 | /* |
- | |
1545 | * NOTE: Driver's shouldn't ever call drm_mode_group_init_legacy_group - it is |
- | |
1546 | * the drm core's responsibility to set up mode control groups. |
- | |
1547 | */ |
- | |
1548 | int drm_mode_group_init_legacy_group(struct drm_device *dev, |
- | |
1549 | struct drm_mode_group *group) |
- | |
1550 | { |
- | |
1551 | struct drm_crtc *crtc; |
- | |
1552 | struct drm_encoder *encoder; |
- | |
1553 | struct drm_connector *connector; |
- | |
1554 | struct drm_bridge *bridge; |
- | |
1555 | int ret; |
- | |
1556 | - | ||
1557 | if ((ret = drm_mode_group_init(dev, group))) |
- | |
1558 | return ret; |
- | |
1559 | - | ||
1560 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
- | |
1561 | group->id_list[group->num_crtcs++] = crtc->base.id; |
- | |
1562 | - | ||
1563 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
- | |
1564 | group->id_list[group->num_crtcs + group->num_encoders++] = |
- | |
1565 | encoder->base.id; |
- | |
1566 | - | ||
1567 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
- | |
1568 | group->id_list[group->num_crtcs + group->num_encoders + |
- | |
1569 | group->num_connectors++] = connector->base.id; |
- | |
1570 | - | ||
1571 | list_for_each_entry(bridge, &dev->mode_config.bridge_list, head) |
- | |
1572 | group->id_list[group->num_crtcs + group->num_encoders + |
- | |
1573 | group->num_connectors + group->num_bridges++] = |
- | |
1574 | bridge->base.id; |
- | |
1575 | - | ||
1576 | return 0; |
- | |
1577 | } |
- | |
1578 | EXPORT_SYMBOL(drm_mode_group_init_legacy_group); |
- | |
1579 | - | ||
1580 | void drm_reinit_primary_mode_group(struct drm_device *dev) |
- | |
1581 | { |
- | |
1582 | drm_modeset_lock_all(dev); |
- | |
1583 | drm_mode_group_destroy(&dev->primary->mode_group); |
- | |
1584 | drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group); |
- | |
1585 | drm_modeset_unlock_all(dev); |
- | |
1586 | } |
- | |
1587 | EXPORT_SYMBOL(drm_reinit_primary_mode_group); |
- | |
1588 | - | ||
1589 | /** |
- | |
1590 | * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo |
- | |
1591 | * @out: drm_mode_modeinfo struct to return to the user |
- | |
1592 | * @in: drm_display_mode to use |
- | |
1593 | * |
- | |
1594 | * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to |
- | |
1595 | * the user. |
- | |
1596 | */ |
- | |
1597 | static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, |
- | |
1598 | const struct drm_display_mode *in) |
- | |
1599 | { |
- | |
1600 | WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || |
- | |
1601 | in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || |
- | |
1602 | in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || |
- | |
1603 | in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || |
- | |
1604 | in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, |
- | |
1605 | "timing values too large for mode info\n"); |
- | |
1606 | - | ||
1607 | out->clock = in->clock; |
- | |
1608 | out->hdisplay = in->hdisplay; |
- | |
1609 | out->hsync_start = in->hsync_start; |
- | |
1610 | out->hsync_end = in->hsync_end; |
- | |
1611 | out->htotal = in->htotal; |
- | |
1612 | out->hskew = in->hskew; |
- | |
1613 | out->vdisplay = in->vdisplay; |
- | |
1614 | out->vsync_start = in->vsync_start; |
- | |
1615 | out->vsync_end = in->vsync_end; |
- | |
1616 | out->vtotal = in->vtotal; |
- | |
1617 | out->vscan = in->vscan; |
- | |
1618 | out->vrefresh = in->vrefresh; |
- | |
1619 | out->flags = in->flags; |
- | |
1620 | out->type = in->type; |
- | |
1621 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
- | |
1622 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
- | |
1623 | } |
- | |
1624 | - | ||
1625 | /** |
- | |
1626 | * drm_crtc_convert_umode - convert a modeinfo into a drm_display_mode |
- | |
1627 | * @out: drm_display_mode to return to the user |
- | |
1628 | * @in: drm_mode_modeinfo to use |
- | |
1629 | * |
- | |
1630 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
- | |
1631 | * the caller. |
- | |
1632 | * |
- | |
1633 | * Returns: |
- | |
1634 | * Zero on success, negative errno on failure. |
- | |
1635 | */ |
- | |
1636 | static int drm_crtc_convert_umode(struct drm_display_mode *out, |
- | |
1637 | const struct drm_mode_modeinfo *in) |
- | |
1638 | { |
- | |
1639 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
- | |
1640 | return -ERANGE; |
- | |
1641 | - | ||
1642 | if ((in->flags & DRM_MODE_FLAG_3D_MASK) > DRM_MODE_FLAG_3D_MAX) |
- | |
1643 | return -EINVAL; |
- | |
1644 | - | ||
1645 | out->clock = in->clock; |
- | |
1646 | out->hdisplay = in->hdisplay; |
- | |
1647 | out->hsync_start = in->hsync_start; |
- | |
1648 | out->hsync_end = in->hsync_end; |
- | |
1649 | out->htotal = in->htotal; |
- | |
1650 | out->hskew = in->hskew; |
- | |
1651 | out->vdisplay = in->vdisplay; |
- | |
1652 | out->vsync_start = in->vsync_start; |
- | |
1653 | out->vsync_end = in->vsync_end; |
- | |
1654 | out->vtotal = in->vtotal; |
- | |
1655 | out->vscan = in->vscan; |
- | |
1656 | out->vrefresh = in->vrefresh; |
- | |
1657 | out->flags = in->flags; |
- | |
1658 | out->type = in->type; |
- | |
1659 | strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); |
- | |
1660 | out->name[DRM_DISPLAY_MODE_LEN-1] = 0; |
- | |
1661 | - | ||
1662 | return 0; |
- | |
1663 | } |
- | |
1664 | - | ||
1665 | 1714 | ||
1666 | #if 0 |
1715 | #if 0 |
1667 | /** |
1716 | /** |
1668 | * drm_mode_getresources - get graphics configuration |
1717 | * drm_mode_getresources - get graphics configuration |
1669 | * @dev: drm device for the ioctl |
1718 | * @dev: drm device for the ioctl |
Line 1690... | Line 1739... | ||
1690 | int ret = 0; |
1739 | int ret = 0; |
1691 | int connector_count = 0; |
1740 | int connector_count = 0; |
1692 | int crtc_count = 0; |
1741 | int crtc_count = 0; |
1693 | int fb_count = 0; |
1742 | int fb_count = 0; |
1694 | int encoder_count = 0; |
1743 | int encoder_count = 0; |
1695 | int copied = 0, i; |
1744 | int copied = 0; |
1696 | uint32_t __user *fb_id; |
1745 | uint32_t __user *fb_id; |
1697 | uint32_t __user *crtc_id; |
1746 | uint32_t __user *crtc_id; |
1698 | uint32_t __user *connector_id; |
1747 | uint32_t __user *connector_id; |
1699 | uint32_t __user *encoder_id; |
1748 | uint32_t __user *encoder_id; |
1700 | struct drm_mode_group *mode_group; |
- | |
Line 1701... | Line 1749... | ||
1701 | 1749 | ||
1702 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1750 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1728... | Line 1776... | ||
1728 | mutex_unlock(&file_priv->fbs_lock); |
1776 | mutex_unlock(&file_priv->fbs_lock); |
Line 1729... | Line 1777... | ||
1729 | 1777 | ||
1730 | /* mode_config.mutex protects the connector list against e.g. DP MST |
1778 | /* mode_config.mutex protects the connector list against e.g. DP MST |
1731 | * connector hot-adding. CRTC/Plane lists are invariant. */ |
1779 | * connector hot-adding. CRTC/Plane lists are invariant. */ |
1732 | mutex_lock(&dev->mode_config.mutex); |
- | |
1733 | if (!drm_is_primary_client(file_priv)) { |
- | |
1734 | - | ||
1735 | mode_group = NULL; |
1780 | mutex_lock(&dev->mode_config.mutex); |
1736 | list_for_each(lh, &dev->mode_config.crtc_list) |
1781 | drm_for_each_crtc(crtc, dev) |
Line 1737... | Line 1782... | ||
1737 | crtc_count++; |
1782 | crtc_count++; |
1738 | 1783 | ||
Line 1739... | Line 1784... | ||
1739 | list_for_each(lh, &dev->mode_config.connector_list) |
1784 | drm_for_each_connector(connector, dev) |
1740 | connector_count++; |
1785 | connector_count++; |
1741 | - | ||
1742 | list_for_each(lh, &dev->mode_config.encoder_list) |
- | |
1743 | encoder_count++; |
- | |
1744 | } else { |
- | |
1745 | - | ||
1746 | mode_group = &file_priv->master->minor->mode_group; |
- | |
1747 | crtc_count = mode_group->num_crtcs; |
- | |
Line 1748... | Line 1786... | ||
1748 | connector_count = mode_group->num_connectors; |
1786 | |
1749 | encoder_count = mode_group->num_encoders; |
1787 | drm_for_each_encoder(encoder, dev) |
1750 | } |
1788 | encoder_count++; |
1751 | 1789 | ||
Line 1752... | Line 1790... | ||
1752 | card_res->max_height = dev->mode_config.max_height; |
1790 | card_res->max_height = dev->mode_config.max_height; |
1753 | card_res->min_height = dev->mode_config.min_height; |
1791 | card_res->min_height = dev->mode_config.min_height; |
1754 | card_res->max_width = dev->mode_config.max_width; |
1792 | card_res->max_width = dev->mode_config.max_width; |
1755 | card_res->min_width = dev->mode_config.min_width; |
1793 | card_res->min_width = dev->mode_config.min_width; |
1756 | - | ||
1757 | /* CRTCs */ |
1794 | |
1758 | if (card_res->count_crtcs >= crtc_count) { |
- | |
1759 | copied = 0; |
1795 | /* CRTCs */ |
1760 | crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; |
1796 | if (card_res->count_crtcs >= crtc_count) { |
1761 | if (!mode_group) { |
1797 | copied = 0; |
1762 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, |
1798 | crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; |
1763 | head) { |
1799 | drm_for_each_crtc(crtc, dev) { |
1764 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
1800 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
1765 | if (put_user(crtc->base.id, crtc_id + copied)) { |
1801 | if (put_user(crtc->base.id, crtc_id + copied)) { |
1766 | ret = -EFAULT; |
- | |
1767 | goto out; |
- | |
1768 | } |
- | |
1769 | copied++; |
- | |
1770 | } |
- | |
1771 | } else { |
- | |
1772 | for (i = 0; i < mode_group->num_crtcs; i++) { |
- | |
1773 | if (put_user(mode_group->id_list[i], |
- | |
1774 | crtc_id + copied)) { |
- | |
1775 | ret = -EFAULT; |
- | |
1776 | goto out; |
1802 | ret = -EFAULT; |
1777 | } |
1803 | goto out; |
Line 1778... | Line 1804... | ||
1778 | copied++; |
1804 | } |
1779 | } |
1805 | copied++; |
1780 | } |
1806 | } |
1781 | } |
1807 | } |
1782 | card_res->count_crtcs = crtc_count; |
- | |
1783 | 1808 | card_res->count_crtcs = crtc_count; |
|
1784 | /* Encoders */ |
- | |
1785 | if (card_res->count_encoders >= encoder_count) { |
- | |
1786 | copied = 0; |
1809 | |
1787 | encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; |
1810 | /* Encoders */ |
1788 | if (!mode_group) { |
1811 | if (card_res->count_encoders >= encoder_count) { |
1789 | list_for_each_entry(encoder, |
1812 | copied = 0; |
1790 | &dev->mode_config.encoder_list, |
1813 | encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; |
1791 | head) { |
1814 | drm_for_each_encoder(encoder, dev) { |
1792 | DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, |
1815 | DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, |
1793 | encoder->name); |
1816 | encoder->name); |
1794 | if (put_user(encoder->base.id, encoder_id + |
1817 | if (put_user(encoder->base.id, encoder_id + |
1795 | copied)) { |
- | |
1796 | ret = -EFAULT; |
- | |
1797 | goto out; |
- | |
1798 | } |
- | |
1799 | copied++; |
- | |
1800 | } |
- | |
1801 | } else { |
- | |
1802 | for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { |
- | |
1803 | if (put_user(mode_group->id_list[i], |
- | |
1804 | encoder_id + copied)) { |
- | |
1805 | ret = -EFAULT; |
- | |
1806 | goto out; |
1818 | copied)) { |
1807 | } |
1819 | ret = -EFAULT; |
Line 1808... | Line 1820... | ||
1808 | copied++; |
1820 | goto out; |
1809 | } |
1821 | } |
1810 | 1822 | copied++; |
|
1811 | } |
1823 | } |
1812 | } |
- | |
1813 | card_res->count_encoders = encoder_count; |
1824 | } |
1814 | - | ||
1815 | /* Connectors */ |
- | |
1816 | if (card_res->count_connectors >= connector_count) { |
1825 | card_res->count_encoders = encoder_count; |
1817 | copied = 0; |
1826 | |
1818 | connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; |
1827 | /* Connectors */ |
1819 | if (!mode_group) { |
1828 | if (card_res->count_connectors >= connector_count) { |
1820 | list_for_each_entry(connector, |
1829 | copied = 0; |
1821 | &dev->mode_config.connector_list, |
1830 | connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; |
1822 | head) { |
1831 | drm_for_each_connector(connector, dev) { |
1823 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
1832 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
1824 | connector->base.id, |
1833 | connector->base.id, |
1825 | connector->name); |
1834 | connector->name); |
1826 | if (put_user(connector->base.id, |
- | |
1827 | connector_id + copied)) { |
- | |
1828 | ret = -EFAULT; |
- | |
1829 | goto out; |
- | |
1830 | } |
- | |
1831 | copied++; |
- | |
1832 | } |
- | |
1833 | } else { |
- | |
1834 | int start = mode_group->num_crtcs + |
- | |
1835 | mode_group->num_encoders; |
- | |
1836 | for (i = start; i < start + mode_group->num_connectors; i++) { |
- | |
1837 | if (put_user(mode_group->id_list[i], |
- | |
1838 | connector_id + copied)) { |
1835 | if (put_user(connector->base.id, |
1839 | ret = -EFAULT; |
1836 | connector_id + copied)) { |
Line 1840... | Line 1837... | ||
1840 | goto out; |
1837 | ret = -EFAULT; |
1841 | } |
1838 | goto out; |
Line 1878... | Line 1875... | ||
1878 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); |
1875 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); |
1879 | if (!crtc) |
1876 | if (!crtc) |
1880 | return -ENOENT; |
1877 | return -ENOENT; |
Line 1881... | Line 1878... | ||
1881 | 1878 | ||
1882 | drm_modeset_lock_crtc(crtc, crtc->primary); |
- | |
1883 | crtc_resp->x = crtc->x; |
- | |
1884 | crtc_resp->y = crtc->y; |
1879 | drm_modeset_lock_crtc(crtc, crtc->primary); |
1885 | crtc_resp->gamma_size = crtc->gamma_size; |
1880 | crtc_resp->gamma_size = crtc->gamma_size; |
1886 | if (crtc->primary->fb) |
1881 | if (crtc->primary->fb) |
1887 | crtc_resp->fb_id = crtc->primary->fb->base.id; |
1882 | crtc_resp->fb_id = crtc->primary->fb->base.id; |
1888 | else |
1883 | else |
Line 1889... | Line 1884... | ||
1889 | crtc_resp->fb_id = 0; |
1884 | crtc_resp->fb_id = 0; |
- | 1885 | ||
- | 1886 | if (crtc->state) { |
|
- | 1887 | crtc_resp->x = crtc->primary->state->src_x >> 16; |
|
- | 1888 | crtc_resp->y = crtc->primary->state->src_y >> 16; |
|
- | 1889 | if (crtc->state->enable) { |
|
Line -... | Line 1890... | ||
- | 1890 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->state->mode); |
|
- | 1891 | crtc_resp->mode_valid = 1; |
|
- | 1892 | ||
- | 1893 | } else { |
|
- | 1894 | crtc_resp->mode_valid = 0; |
|
- | 1895 | } |
|
- | 1896 | } else { |
|
1890 | 1897 | crtc_resp->x = crtc->x; |
|
1891 | if (crtc->enabled) { |
1898 | crtc_resp->y = crtc->y; |
Line 1892... | Line 1899... | ||
1892 | 1899 | if (crtc->enabled) { |
|
1893 | drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); |
1900 | drm_mode_convert_to_umode(&crtc_resp->mode, &crtc->mode); |
1894 | crtc_resp->mode_valid = 1; |
1901 | crtc_resp->mode_valid = 1; |
- | 1902 | ||
1895 | 1903 | } else { |
|
Line 1896... | Line 1904... | ||
1896 | } else { |
1904 | crtc_resp->mode_valid = 0; |
1897 | crtc_resp->mode_valid = 0; |
1905 | } |
Line 1921... | Line 1929... | ||
1921 | if (connector->state) |
1929 | if (connector->state) |
1922 | return connector->state->best_encoder; |
1930 | return connector->state->best_encoder; |
1923 | return connector->encoder; |
1931 | return connector->encoder; |
1924 | } |
1932 | } |
Line -... | Line 1933... | ||
- | 1933 | ||
- | 1934 | /* helper for getconnector and getproperties ioctls */ |
|
- | 1935 | static int get_properties(struct drm_mode_object *obj, bool atomic, |
|
- | 1936 | uint32_t __user *prop_ptr, uint64_t __user *prop_values, |
|
- | 1937 | uint32_t *arg_count_props) |
|
- | 1938 | { |
|
- | 1939 | int props_count; |
|
- | 1940 | int i, ret, copied; |
|
- | 1941 | ||
- | 1942 | props_count = obj->properties->count; |
|
- | 1943 | if (!atomic) |
|
- | 1944 | props_count -= obj->properties->atomic_count; |
|
- | 1945 | ||
- | 1946 | if ((*arg_count_props >= props_count) && props_count) { |
|
- | 1947 | for (i = 0, copied = 0; copied < props_count; i++) { |
|
- | 1948 | struct drm_property *prop = obj->properties->properties[i]; |
|
- | 1949 | uint64_t val; |
|
- | 1950 | ||
- | 1951 | if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) |
|
- | 1952 | continue; |
|
- | 1953 | ||
- | 1954 | ret = drm_object_property_get_value(obj, prop, &val); |
|
- | 1955 | if (ret) |
|
- | 1956 | return ret; |
|
- | 1957 | ||
- | 1958 | if (put_user(prop->base.id, prop_ptr + copied)) |
|
- | 1959 | return -EFAULT; |
|
- | 1960 | ||
- | 1961 | if (put_user(val, prop_values + copied)) |
|
- | 1962 | return -EFAULT; |
|
- | 1963 | ||
- | 1964 | copied++; |
|
- | 1965 | } |
|
- | 1966 | } |
|
- | 1967 | *arg_count_props = props_count; |
|
- | 1968 | ||
- | 1969 | return 0; |
|
- | 1970 | } |
|
1925 | 1971 | ||
1926 | /** |
1972 | /** |
1927 | * drm_mode_getconnector - get connector configuration |
1973 | * drm_mode_getconnector - get connector configuration |
1928 | * @dev: drm device for the ioctl |
1974 | * @dev: drm device for the ioctl |
1929 | * @data: data pointer for the ioctl |
1975 | * @data: data pointer for the ioctl |
Line 1942... | Line 1988... | ||
1942 | struct drm_mode_get_connector *out_resp = data; |
1988 | struct drm_mode_get_connector *out_resp = data; |
1943 | struct drm_connector *connector; |
1989 | struct drm_connector *connector; |
1944 | struct drm_encoder *encoder; |
1990 | struct drm_encoder *encoder; |
1945 | struct drm_display_mode *mode; |
1991 | struct drm_display_mode *mode; |
1946 | int mode_count = 0; |
1992 | int mode_count = 0; |
1947 | int props_count = 0; |
- | |
1948 | int encoders_count = 0; |
1993 | int encoders_count = 0; |
1949 | int ret = 0; |
1994 | int ret = 0; |
1950 | int copied = 0; |
1995 | int copied = 0; |
1951 | int i; |
1996 | int i; |
1952 | struct drm_mode_modeinfo u_mode; |
1997 | struct drm_mode_modeinfo u_mode; |
1953 | struct drm_mode_modeinfo __user *mode_ptr; |
1998 | struct drm_mode_modeinfo __user *mode_ptr; |
1954 | uint32_t __user *prop_ptr; |
- | |
1955 | uint64_t __user *prop_values; |
- | |
1956 | uint32_t __user *encoder_ptr; |
1999 | uint32_t __user *encoder_ptr; |
Line 1957... | Line 2000... | ||
1957 | 2000 | ||
1958 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2001 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1965... | Line 2008... | ||
1965 | mutex_lock(&dev->mode_config.mutex); |
2008 | mutex_lock(&dev->mode_config.mutex); |
Line 1966... | Line 2009... | ||
1966 | 2009 | ||
1967 | connector = drm_connector_find(dev, out_resp->connector_id); |
2010 | connector = drm_connector_find(dev, out_resp->connector_id); |
1968 | if (!connector) { |
2011 | if (!connector) { |
1969 | ret = -ENOENT; |
2012 | ret = -ENOENT; |
1970 | goto out; |
2013 | goto out_unlock; |
Line 1971... | Line -... | ||
1971 | } |
- | |
1972 | - | ||
1973 | props_count = connector->properties.count; |
2014 | } |
1974 | 2015 | ||
1975 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
2016 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) |
1976 | if (connector->encoder_ids[i] != 0) { |
- | |
1977 | encoders_count++; |
- | |
Line 1978... | Line 2017... | ||
1978 | } |
2017 | if (connector->encoder_ids[i] != 0) |
1979 | } |
2018 | encoders_count++; |
1980 | 2019 | ||
1981 | if (out_resp->count_modes == 0) { |
2020 | if (out_resp->count_modes == 0) { |
Line 1994... | Line 2033... | ||
1994 | out_resp->connector_type_id = connector->connector_type_id; |
2033 | out_resp->connector_type_id = connector->connector_type_id; |
1995 | out_resp->mm_width = connector->display_info.width_mm; |
2034 | out_resp->mm_width = connector->display_info.width_mm; |
1996 | out_resp->mm_height = connector->display_info.height_mm; |
2035 | out_resp->mm_height = connector->display_info.height_mm; |
1997 | out_resp->subpixel = connector->display_info.subpixel_order; |
2036 | out_resp->subpixel = connector->display_info.subpixel_order; |
1998 | out_resp->connection = connector->status; |
2037 | out_resp->connection = connector->status; |
1999 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
- | |
Line -... | Line 2038... | ||
- | 2038 | ||
2000 | 2039 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
|
2001 | encoder = drm_connector_get_encoder(connector); |
2040 | encoder = drm_connector_get_encoder(connector); |
2002 | if (encoder) |
2041 | if (encoder) |
2003 | out_resp->encoder_id = encoder->base.id; |
2042 | out_resp->encoder_id = encoder->base.id; |
2004 | else |
2043 | else |
2005 | out_resp->encoder_id = 0; |
- | |
Line 2006... | Line 2044... | ||
2006 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
2044 | out_resp->encoder_id = 0; |
2007 | 2045 | ||
2008 | /* |
2046 | /* |
2009 | * This ioctl is called twice, once to determine how much space is |
2047 | * This ioctl is called twice, once to determine how much space is |
Line 2014... | Line 2052... | ||
2014 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; |
2052 | mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; |
2015 | list_for_each_entry(mode, &connector->modes, head) { |
2053 | list_for_each_entry(mode, &connector->modes, head) { |
2016 | if (!drm_mode_expose_to_userspace(mode, file_priv)) |
2054 | if (!drm_mode_expose_to_userspace(mode, file_priv)) |
2017 | continue; |
2055 | continue; |
Line 2018... | Line 2056... | ||
2018 | 2056 | ||
2019 | drm_crtc_convert_to_umode(&u_mode, mode); |
2057 | drm_mode_convert_to_umode(&u_mode, mode); |
2020 | if (copy_to_user(mode_ptr + copied, |
2058 | if (copy_to_user(mode_ptr + copied, |
2021 | &u_mode, sizeof(u_mode))) { |
2059 | &u_mode, sizeof(u_mode))) { |
2022 | ret = -EFAULT; |
2060 | ret = -EFAULT; |
2023 | goto out; |
2061 | goto out; |
2024 | } |
2062 | } |
2025 | copied++; |
2063 | copied++; |
2026 | } |
2064 | } |
2027 | } |
2065 | } |
Line 2028... | Line 2066... | ||
2028 | out_resp->count_modes = mode_count; |
2066 | out_resp->count_modes = mode_count; |
2029 | - | ||
2030 | if ((out_resp->count_props >= props_count) && props_count) { |
2067 | |
2031 | copied = 0; |
2068 | ret = get_properties(&connector->base, file_priv->atomic, |
2032 | prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); |
- | |
2033 | prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); |
2069 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), |
2034 | for (i = 0; i < connector->properties.count; i++) { |
- | |
2035 | if (put_user(connector->properties.ids[i], |
- | |
2036 | prop_ptr + copied)) { |
- | |
2037 | ret = -EFAULT; |
2070 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), |
2038 | goto out; |
- | |
2039 | } |
- | |
2040 | - | ||
2041 | if (put_user(connector->properties.values[i], |
- | |
2042 | prop_values + copied)) { |
2071 | &out_resp->count_props); |
2043 | ret = -EFAULT; |
- | |
2044 | goto out; |
- | |
2045 | } |
- | |
2046 | copied++; |
- | |
2047 | } |
- | |
Line 2048... | Line 2072... | ||
2048 | } |
2072 | if (ret) |
2049 | out_resp->count_props = props_count; |
2073 | goto out; |
2050 | 2074 | ||
2051 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
2075 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
Line 2063... | Line 2087... | ||
2063 | } |
2087 | } |
2064 | } |
2088 | } |
2065 | out_resp->count_encoders = encoders_count; |
2089 | out_resp->count_encoders = encoders_count; |
Line 2066... | Line 2090... | ||
2066 | 2090 | ||
- | 2091 | out: |
|
- | 2092 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
|
- | 2093 | ||
2067 | out: |
2094 | out_unlock: |
Line 2068... | Line 2095... | ||
2068 | mutex_unlock(&dev->mode_config.mutex); |
2095 | mutex_unlock(&dev->mode_config.mutex); |
2069 | 2096 | ||
Line 2076... | Line 2103... | ||
2076 | struct drm_device *dev = encoder->dev; |
2103 | struct drm_device *dev = encoder->dev; |
2077 | bool uses_atomic = false; |
2104 | bool uses_atomic = false; |
Line 2078... | Line 2105... | ||
2078 | 2105 | ||
2079 | /* For atomic drivers only state objects are synchronously updated and |
2106 | /* For atomic drivers only state objects are synchronously updated and |
2080 | * protected by modeset locks, so check those first. */ |
2107 | * protected by modeset locks, so check those first. */ |
2081 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
2108 | drm_for_each_connector(connector, dev) { |
2082 | if (!connector->state) |
2109 | if (!connector->state) |
Line 2083... | Line 2110... | ||
2083 | continue; |
2110 | continue; |
Line 2126... | Line 2153... | ||
2126 | 2153 | ||
2127 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2154 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
2128 | crtc = drm_encoder_get_crtc(encoder); |
2155 | crtc = drm_encoder_get_crtc(encoder); |
2129 | if (crtc) |
2156 | if (crtc) |
2130 | enc_resp->crtc_id = crtc->base.id; |
- | |
2131 | else if (encoder->crtc) |
- | |
2132 | enc_resp->crtc_id = encoder->crtc->base.id; |
2157 | enc_resp->crtc_id = crtc->base.id; |
2133 | else |
2158 | else |
2134 | enc_resp->crtc_id = 0; |
2159 | enc_resp->crtc_id = 0; |
Line 2135... | Line 2160... | ||
2135 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
2160 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
Line 2182... | Line 2207... | ||
2182 | if (num_planes && |
2207 | if (num_planes && |
2183 | (plane_resp->count_planes >= num_planes)) { |
2208 | (plane_resp->count_planes >= num_planes)) { |
2184 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
2209 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
Line 2185... | Line 2210... | ||
2185 | 2210 | ||
2186 | /* Plane lists are invariant, no locking needed. */ |
2211 | /* Plane lists are invariant, no locking needed. */ |
2187 | list_for_each_entry(plane, &config->plane_list, head) { |
2212 | drm_for_each_plane(plane, dev) { |
2188 | /* |
2213 | /* |
2189 | * Unless userspace set the 'universal planes' |
2214 | * Unless userspace set the 'universal planes' |
2190 | * capability bit, only advertise overlays. |
2215 | * capability bit, only advertise overlays. |
2191 | */ |
2216 | */ |
Line 2261... | Line 2286... | ||
2261 | } |
2286 | } |
2262 | plane_resp->count_format_types = plane->format_count; |
2287 | plane_resp->count_format_types = plane->format_count; |
Line 2263... | Line 2288... | ||
2263 | 2288 | ||
2264 | return 0; |
2289 | return 0; |
- | 2290 | } |
|
- | 2291 | #endif |
|
- | 2292 | ||
- | 2293 | /** |
|
- | 2294 | * drm_plane_check_pixel_format - Check if the plane supports the pixel format |
|
- | 2295 | * @plane: plane to check for format support |
|
- | 2296 | * @format: the pixel format |
|
- | 2297 | * |
|
- | 2298 | * Returns: |
|
- | 2299 | * Zero of @plane has @format in its list of supported pixel formats, -EINVAL |
|
- | 2300 | * otherwise. |
|
- | 2301 | */ |
|
- | 2302 | int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format) |
|
- | 2303 | { |
|
- | 2304 | unsigned int i; |
|
- | 2305 | ||
- | 2306 | for (i = 0; i < plane->format_count; i++) { |
|
- | 2307 | if (format == plane->format_types[i]) |
|
- | 2308 | return 0; |
|
- | 2309 | } |
|
- | 2310 | ||
- | 2311 | return -EINVAL; |
|
- | 2312 | } |
|
- | 2313 | ||
- | 2314 | static int check_src_coords(uint32_t src_x, uint32_t src_y, |
|
- | 2315 | uint32_t src_w, uint32_t src_h, |
|
- | 2316 | const struct drm_framebuffer *fb) |
|
- | 2317 | { |
|
- | 2318 | unsigned int fb_width, fb_height; |
|
- | 2319 | ||
- | 2320 | fb_width = fb->width << 16; |
|
- | 2321 | fb_height = fb->height << 16; |
|
- | 2322 | ||
- | 2323 | /* Make sure source coordinates are inside the fb. */ |
|
- | 2324 | if (src_w > fb_width || |
|
- | 2325 | src_x > fb_width - src_w || |
|
- | 2326 | src_h > fb_height || |
|
- | 2327 | src_y > fb_height - src_h) { |
|
- | 2328 | DRM_DEBUG_KMS("Invalid source coordinates " |
|
- | 2329 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", |
|
- | 2330 | src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, |
|
- | 2331 | src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, |
|
- | 2332 | src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, |
|
- | 2333 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); |
|
- | 2334 | return -ENOSPC; |
|
- | 2335 | } |
|
- | 2336 | ||
- | 2337 | return 0; |
|
Line 2265... | Line 2338... | ||
2265 | } |
2338 | } |
2266 | 2339 | ||
2267 | /* |
2340 | /* |
2268 | * setplane_internal - setplane handler for internal callers |
2341 | * setplane_internal - setplane handler for internal callers |
Line 2281... | Line 2354... | ||
2281 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
2354 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
2282 | uint32_t src_x, uint32_t src_y, |
2355 | uint32_t src_x, uint32_t src_y, |
2283 | uint32_t src_w, uint32_t src_h) |
2356 | uint32_t src_w, uint32_t src_h) |
2284 | { |
2357 | { |
2285 | int ret = 0; |
2358 | int ret = 0; |
2286 | unsigned int fb_width, fb_height; |
- | |
2287 | unsigned int i; |
- | |
Line 2288... | Line 2359... | ||
2288 | 2359 | ||
2289 | /* No fb means shut it down */ |
2360 | /* No fb means shut it down */ |
2290 | if (!fb) { |
2361 | if (!fb) { |
2291 | plane->old_fb = plane->fb; |
2362 | plane->old_fb = plane->fb; |
Line 2305... | Line 2376... | ||
2305 | ret = -EINVAL; |
2376 | ret = -EINVAL; |
2306 | goto out; |
2377 | goto out; |
2307 | } |
2378 | } |
Line 2308... | Line 2379... | ||
2308 | 2379 | ||
2309 | /* Check whether this plane supports the fb pixel format. */ |
- | |
2310 | for (i = 0; i < plane->format_count; i++) |
2380 | /* Check whether this plane supports the fb pixel format. */ |
2311 | if (fb->pixel_format == plane->format_types[i]) |
2381 | ret = drm_plane_check_pixel_format(plane, fb->pixel_format); |
2312 | break; |
- | |
2313 | if (i == plane->format_count) { |
2382 | if (ret) { |
2314 | DRM_DEBUG_KMS("Invalid pixel format %s\n", |
2383 | DRM_DEBUG_KMS("Invalid pixel format %s\n", |
2315 | drm_get_format_name(fb->pixel_format)); |
- | |
2316 | ret = -EINVAL; |
2384 | drm_get_format_name(fb->pixel_format)); |
2317 | goto out; |
2385 | goto out; |
Line 2318... | Line -... | ||
2318 | } |
- | |
2319 | - | ||
2320 | fb_width = fb->width << 16; |
- | |
2321 | fb_height = fb->height << 16; |
2386 | } |
2322 | 2387 | ||
2323 | /* Make sure source coordinates are inside the fb. */ |
2388 | /* Give drivers some help against integer overflows */ |
2324 | if (src_w > fb_width || |
2389 | if (crtc_w > INT_MAX || |
2325 | src_x > fb_width - src_w || |
2390 | crtc_x > INT_MAX - (int32_t) crtc_w || |
2326 | src_h > fb_height || |
2391 | crtc_h > INT_MAX || |
2327 | src_y > fb_height - src_h) { |
- | |
2328 | DRM_DEBUG_KMS("Invalid source coordinates " |
- | |
2329 | "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", |
2392 | crtc_y > INT_MAX - (int32_t) crtc_h) { |
2330 | src_w >> 16, ((src_w & 0xffff) * 15625) >> 10, |
- | |
2331 | src_h >> 16, ((src_h & 0xffff) * 15625) >> 10, |
- | |
2332 | src_x >> 16, ((src_x & 0xffff) * 15625) >> 10, |
2393 | DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", |
2333 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); |
2394 | crtc_w, crtc_h, crtc_x, crtc_y); |
2334 | ret = -ENOSPC; |
2395 | ret = -ERANGE; |
Line -... | Line 2396... | ||
- | 2396 | goto out; |
|
- | 2397 | } |
|
- | 2398 | ||
- | 2399 | ret = check_src_coords(src_x, src_y, src_w, src_h, fb); |
|
2335 | goto out; |
2400 | if (ret) |
2336 | } |
2401 | goto out; |
2337 | 2402 | ||
2338 | plane->old_fb = plane->fb; |
2403 | plane->old_fb = plane->fb; |
2339 | ret = plane->funcs->update_plane(plane, crtc, fb, |
2404 | ret = plane->funcs->update_plane(plane, crtc, fb, |
Line 2399... | Line 2464... | ||
2399 | struct drm_framebuffer *fb = NULL; |
2464 | struct drm_framebuffer *fb = NULL; |
Line 2400... | Line 2465... | ||
2400 | 2465 | ||
2401 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2466 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2402... | Line -... | ||
2402 | return -EINVAL; |
- | |
2403 | - | ||
2404 | /* Give drivers some help against integer overflows */ |
- | |
2405 | if (plane_req->crtc_w > INT_MAX || |
- | |
2406 | plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || |
- | |
2407 | plane_req->crtc_h > INT_MAX || |
- | |
2408 | plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { |
- | |
2409 | DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", |
- | |
2410 | plane_req->crtc_w, plane_req->crtc_h, |
- | |
2411 | plane_req->crtc_x, plane_req->crtc_y); |
- | |
2412 | return -ERANGE; |
- | |
2413 | } |
2467 | return -EINVAL; |
2414 | 2468 | ||
2415 | /* |
2469 | /* |
2416 | * First, find the plane, crtc, and fb objects. If not available, |
2470 | * First, find the plane, crtc, and fb objects. If not available, |
2417 | * we don't bother to call the driver. |
2471 | * we don't bother to call the driver. |
Line 2447... | Line 2501... | ||
2447 | plane_req->crtc_x, plane_req->crtc_y, |
2501 | plane_req->crtc_x, plane_req->crtc_y, |
2448 | plane_req->crtc_w, plane_req->crtc_h, |
2502 | plane_req->crtc_w, plane_req->crtc_h, |
2449 | plane_req->src_x, plane_req->src_y, |
2503 | plane_req->src_x, plane_req->src_y, |
2450 | plane_req->src_w, plane_req->src_h); |
2504 | plane_req->src_w, plane_req->src_h); |
2451 | } |
2505 | } |
2452 | #endif |
- | |
Line 2453... | Line 2506... | ||
2453 | 2506 | ||
2454 | /** |
2507 | /** |
2455 | * drm_mode_set_config_internal - helper to call ->set_config |
2508 | * drm_mode_set_config_internal - helper to call ->set_config |
2456 | * @set: modeset config to set |
2509 | * @set: modeset config to set |
Line 2471... | Line 2524... | ||
2471 | /* |
2524 | /* |
2472 | * NOTE: ->set_config can also disable other crtcs (if we steal all |
2525 | * NOTE: ->set_config can also disable other crtcs (if we steal all |
2473 | * connectors from it), hence we need to refcount the fbs across all |
2526 | * connectors from it), hence we need to refcount the fbs across all |
2474 | * crtcs. Atomic modeset will have saner semantics ... |
2527 | * crtcs. Atomic modeset will have saner semantics ... |
2475 | */ |
2528 | */ |
2476 | list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) |
2529 | drm_for_each_crtc(tmp, crtc->dev) |
2477 | tmp->primary->old_fb = tmp->primary->fb; |
2530 | tmp->primary->old_fb = tmp->primary->fb; |
Line 2478... | Line 2531... | ||
2478 | 2531 | ||
Line 2479... | Line 2532... | ||
2479 | fb = set->fb; |
2532 | fb = set->fb; |
2480 | 2533 | ||
2481 | ret = crtc->funcs->set_config(set); |
2534 | ret = crtc->funcs->set_config(set); |
2482 | if (ret == 0) { |
2535 | if (ret == 0) { |
2483 | crtc->primary->crtc = crtc; |
2536 | crtc->primary->crtc = crtc; |
Line 2484... | Line 2537... | ||
2484 | crtc->primary->fb = fb; |
2537 | crtc->primary->fb = fb; |
2485 | } |
2538 | } |
2486 | 2539 | ||
2487 | list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) { |
2540 | drm_for_each_crtc(tmp, crtc->dev) { |
2488 | if (tmp->primary->fb) |
2541 | if (tmp->primary->fb) |
2489 | drm_framebuffer_reference(tmp->primary->fb); |
2542 | drm_framebuffer_reference(tmp->primary->fb); |
Line 2490... | Line 2543... | ||
2490 | // if (tmp->old_fb) |
2543 | // if (tmp->old_fb) |
2491 | // drm_framebuffer_unreference(tmp->old_fb); |
2544 | // drm_framebuffer_unreference(tmp->old_fb); |
2492 | } |
2545 | } |
Line -... | Line 2546... | ||
- | 2546 | ||
- | 2547 | return ret; |
|
- | 2548 | } |
|
- | 2549 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
|
- | 2550 | ||
2493 | 2551 | /** |
|
- | 2552 | * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode |
|
- | 2553 | * @mode: mode to query |
|
- | 2554 | * @hdisplay: hdisplay value to fill in |
|
- | 2555 | * @vdisplay: vdisplay value to fill in |
|
- | 2556 | * |
|
- | 2557 | * The vdisplay value will be doubled if the specified mode is a stereo mode of |
|
- | 2558 | * the appropriate layout. |
|
- | 2559 | */ |
|
- | 2560 | void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, |
|
- | 2561 | int *hdisplay, int *vdisplay) |
|
- | 2562 | { |
|
- | 2563 | struct drm_display_mode adjusted; |
|
- | 2564 | ||
- | 2565 | drm_mode_copy(&adjusted, mode); |
|
- | 2566 | drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY); |
|
2494 | return ret; |
2567 | *hdisplay = adjusted.crtc_hdisplay; |
2495 | } |
2568 | *vdisplay = adjusted.crtc_vdisplay; |
2496 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
2569 | } |
2497 | 2570 | EXPORT_SYMBOL(drm_crtc_get_hv_timing); |
|
2498 | #if 0 |
2571 | |
Line 2511... | Line 2584... | ||
2511 | const struct drm_framebuffer *fb) |
2584 | const struct drm_framebuffer *fb) |
Line 2512... | Line 2585... | ||
2512 | 2585 | ||
2513 | { |
2586 | { |
Line 2514... | Line -... | ||
2514 | int hdisplay, vdisplay; |
- | |
2515 | - | ||
2516 | hdisplay = mode->hdisplay; |
- | |
2517 | vdisplay = mode->vdisplay; |
- | |
2518 | 2587 | int hdisplay, vdisplay; |
|
Line 2519... | Line -... | ||
2519 | if (drm_mode_is_stereo(mode)) { |
- | |
2520 | struct drm_display_mode adjusted = *mode; |
2588 | |
2521 | 2589 | drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); |
|
2522 | drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); |
- | |
2523 | hdisplay = adjusted.crtc_hdisplay; |
- | |
2524 | vdisplay = adjusted.crtc_vdisplay; |
2590 | |
2525 | } |
2591 | if (crtc->state && |
Line 2526... | Line -... | ||
2526 | - | ||
2527 | if (crtc->invert_dimensions) |
- | |
2528 | swap(hdisplay, vdisplay); |
2592 | crtc->primary->state->rotation & (BIT(DRM_ROTATE_90) | |
2529 | 2593 | BIT(DRM_ROTATE_270))) |
|
2530 | if (hdisplay > fb->width || |
- | |
2531 | vdisplay > fb->height || |
- | |
2532 | x > fb->width - hdisplay || |
- | |
2533 | y > fb->height - vdisplay) { |
- | |
2534 | DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", |
- | |
2535 | fb->width, fb->height, hdisplay, vdisplay, x, y, |
- | |
2536 | crtc->invert_dimensions ? " (inverted)" : ""); |
- | |
2537 | return -ENOSPC; |
2594 | swap(hdisplay, vdisplay); |
2538 | } |
2595 | |
Line -... | Line 2596... | ||
- | 2596 | return check_src_coords(x << 16, y << 16, |
|
2539 | 2597 | hdisplay << 16, vdisplay << 16, fb); |
|
2540 | return 0; |
2598 | } |
2541 | } |
2599 | EXPORT_SYMBOL(drm_crtc_check_viewport); |
2542 | EXPORT_SYMBOL(drm_crtc_check_viewport); |
2600 | |
2543 | 2601 | #if 0 |
|
Line 2569... | Line 2627... | ||
2569 | int i; |
2627 | int i; |
Line 2570... | Line 2628... | ||
2570 | 2628 | ||
2571 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2629 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line -... | Line 2630... | ||
- | 2630 | return -EINVAL; |
|
- | 2631 | ||
2572 | return -EINVAL; |
2632 | /* |
- | 2633 | * Universal plane src offsets are only 16.16, prevent havoc for |
|
2573 | 2634 | * drivers using universal plane code internally. |
|
2574 | /* For some reason crtc x/y offsets are signed internally. */ |
2635 | */ |
Line 2575... | Line 2636... | ||
2575 | if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) |
2636 | if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) |
2576 | return -ERANGE; |
2637 | return -ERANGE; |
2577 | 2638 | ||
Line 2610... | Line 2671... | ||
2610 | if (!mode) { |
2671 | if (!mode) { |
2611 | ret = -ENOMEM; |
2672 | ret = -ENOMEM; |
2612 | goto out; |
2673 | goto out; |
2613 | } |
2674 | } |
Line 2614... | Line 2675... | ||
2614 | 2675 | ||
2615 | ret = drm_crtc_convert_umode(mode, &crtc_req->mode); |
2676 | ret = drm_mode_convert_umode(mode, &crtc_req->mode); |
2616 | if (ret) { |
2677 | if (ret) { |
2617 | DRM_DEBUG_KMS("Invalid mode\n"); |
2678 | DRM_DEBUG_KMS("Invalid mode\n"); |
2618 | goto out; |
2679 | goto out; |
Line 2619... | Line 2680... | ||
2619 | } |
2680 | } |
Line -... | Line 2681... | ||
- | 2681 | ||
- | 2682 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
|
- | 2683 | ||
- | 2684 | /* |
|
- | 2685 | * Check whether the primary plane supports the fb pixel format. |
|
- | 2686 | * Drivers not implementing the universal planes API use a |
|
- | 2687 | * default formats list provided by the DRM core which doesn't |
|
- | 2688 | * match real hardware capabilities. Skip the check in that |
|
- | 2689 | * case. |
|
- | 2690 | */ |
|
- | 2691 | if (!crtc->primary->format_default) { |
|
- | 2692 | ret = drm_plane_check_pixel_format(crtc->primary, |
|
- | 2693 | fb->pixel_format); |
|
- | 2694 | if (ret) { |
|
- | 2695 | DRM_DEBUG_KMS("Invalid pixel format %s\n", |
|
- | 2696 | drm_get_format_name(fb->pixel_format)); |
|
- | 2697 | goto out; |
|
2620 | 2698 | } |
|
2621 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
2699 | } |
2622 | 2700 | ||
2623 | ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, |
2701 | ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, |
Line 2647... | Line 2725... | ||
2647 | if (crtc_req->count_connectors > config->num_connector) { |
2725 | if (crtc_req->count_connectors > config->num_connector) { |
2648 | ret = -EINVAL; |
2726 | ret = -EINVAL; |
2649 | goto out; |
2727 | goto out; |
2650 | } |
2728 | } |
Line 2651... | Line 2729... | ||
2651 | 2729 | ||
2652 | connector_set = kmalloc(crtc_req->count_connectors * |
2730 | connector_set = kmalloc_array(crtc_req->count_connectors, |
2653 | sizeof(struct drm_connector *), |
2731 | sizeof(struct drm_connector *), |
2654 | GFP_KERNEL); |
2732 | GFP_KERNEL); |
2655 | if (!connector_set) { |
2733 | if (!connector_set) { |
2656 | ret = -ENOMEM; |
2734 | ret = -ENOMEM; |
2657 | goto out; |
2735 | goto out; |
Line 2658... | Line 2736... | ||
2658 | } |
2736 | } |
2659 | 2737 | ||
2660 | for (i = 0; i < crtc_req->count_connectors; i++) { |
2738 | for (i = 0; i < crtc_req->count_connectors; i++) { |
2661 | set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; |
2739 | set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; |
2662 | if (get_user(out_id, &set_connectors_ptr[i])) { |
2740 | // if (get_user(out_id, &set_connectors_ptr[i])) { |
2663 | ret = -EFAULT; |
2741 | // ret = -EFAULT; |
Line 2664... | Line 2742... | ||
2664 | goto out; |
2742 | // goto out; |
2665 | } |
2743 | // } |
2666 | 2744 | ||
2667 | connector = drm_connector_find(dev, out_id); |
2745 | connector = drm_connector_find(dev, out_id); |
Line 2799... | Line 2877... | ||
2799 | */ |
2877 | */ |
2800 | int drm_mode_cursor2_ioctl(struct drm_device *dev, |
2878 | int drm_mode_cursor2_ioctl(struct drm_device *dev, |
2801 | void *data, struct drm_file *file_priv) |
2879 | void *data, struct drm_file *file_priv) |
2802 | { |
2880 | { |
2803 | struct drm_mode_cursor2 *req = data; |
2881 | struct drm_mode_cursor2 *req = data; |
- | 2882 | ||
2804 | return drm_mode_cursor_common(dev, req, file_priv); |
2883 | return drm_mode_cursor_common(dev, req, file_priv); |
2805 | } |
2884 | } |
2806 | #endif |
2885 | #endif |
Line 2807... | Line 2886... | ||
2807 | 2886 | ||
Line 3002... | Line 3081... | ||
3002 | 3081 | ||
3003 | if (r->pitches[i] < width * cpp) { |
3082 | if (r->pitches[i] < width * cpp) { |
3004 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); |
3083 | DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); |
3005 | return -EINVAL; |
3084 | return -EINVAL; |
- | 3085 | } |
|
- | 3086 | ||
- | 3087 | if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) { |
|
- | 3088 | DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n", |
|
- | 3089 | r->modifier[i], i); |
|
- | 3090 | return -EINVAL; |
|
- | 3091 | } |
|
- | 3092 | ||
- | 3093 | /* modifier specific checks: */ |
|
- | 3094 | switch (r->modifier[i]) { |
|
- | 3095 | case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: |
|
- | 3096 | /* NOTE: the pitch restriction may be lifted later if it turns |
|
- | 3097 | * out that no hw has this restriction: |
|
- | 3098 | */ |
|
- | 3099 | if (r->pixel_format != DRM_FORMAT_NV12 || |
|
- | 3100 | width % 128 || height % 32 || |
|
- | 3101 | r->pitches[i] % 128) { |
|
- | 3102 | DRM_DEBUG_KMS("bad modifier data for plane %d\n", i); |
|
- | 3103 | return -EINVAL; |
|
- | 3104 | } |
|
- | 3105 | break; |
|
- | 3106 | ||
- | 3107 | default: |
|
- | 3108 | break; |
|
- | 3109 | } |
|
- | 3110 | } |
|
- | 3111 | ||
- | 3112 | for (i = num_planes; i < 4; i++) { |
|
- | 3113 | if (r->modifier[i]) { |
|
- | 3114 | DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i); |
|
- | 3115 | return -EINVAL; |
|
- | 3116 | } |
|
- | 3117 | ||
- | 3118 | /* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */ |
|
- | 3119 | if (!(r->flags & DRM_MODE_FB_MODIFIERS)) |
|
- | 3120 | continue; |
|
- | 3121 | ||
- | 3122 | if (r->handles[i]) { |
|
- | 3123 | DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i); |
|
- | 3124 | return -EINVAL; |
|
- | 3125 | } |
|
- | 3126 | ||
- | 3127 | if (r->pitches[i]) { |
|
- | 3128 | DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i); |
|
- | 3129 | return -EINVAL; |
|
- | 3130 | } |
|
- | 3131 | ||
- | 3132 | if (r->offsets[i]) { |
|
- | 3133 | DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i); |
|
- | 3134 | return -EINVAL; |
|
3006 | } |
3135 | } |
Line 3007... | Line 3136... | ||
3007 | } |
3136 | } |
3008 | 3137 | ||
Line -... | Line 3138... | ||
- | 3138 | return 0; |
|
3009 | return 0; |
3139 | } |
3010 | } |
3140 | |
3011 | 3141 | static struct drm_framebuffer * |
|
3012 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, |
3142 | internal_framebuffer_create(struct drm_device *dev, |
3013 | struct drm_mode_fb_cmd2 *r, |
3143 | struct drm_mode_fb_cmd2 *r, |
3014 | struct drm_file *file_priv) |
3144 | struct drm_file *file_priv) |
3015 | { |
3145 | { |
Line 3016... | Line 3146... | ||
3016 | struct drm_mode_config *config = &dev->mode_config; |
3146 | struct drm_mode_config *config = &dev->mode_config; |
3017 | struct drm_framebuffer *fb; |
3147 | struct drm_framebuffer *fb; |
3018 | int ret; |
3148 | int ret; |
3019 | 3149 | ||
Line 3020... | Line 3150... | ||
3020 | if (r->flags & ~DRM_MODE_FB_INTERLACED) { |
3150 | if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) { |
Line 3031... | Line 3161... | ||
3031 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", |
3161 | DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", |
3032 | r->height, config->min_height, config->max_height); |
3162 | r->height, config->min_height, config->max_height); |
3033 | return ERR_PTR(-EINVAL); |
3163 | return ERR_PTR(-EINVAL); |
3034 | } |
3164 | } |
Line -... | Line 3165... | ||
- | 3165 | ||
- | 3166 | if (r->flags & DRM_MODE_FB_MODIFIERS && |
|
- | 3167 | !dev->mode_config.allow_fb_modifiers) { |
|
- | 3168 | DRM_DEBUG_KMS("driver does not support fb modifiers\n"); |
|
- | 3169 | return ERR_PTR(-EINVAL); |
|
- | 3170 | } |
|
3035 | 3171 | ||
3036 | ret = framebuffer_check(r); |
3172 | ret = framebuffer_check(r); |
3037 | if (ret) |
3173 | if (ret) |
Line 3038... | Line 3174... | ||
3038 | return ERR_PTR(ret); |
3174 | return ERR_PTR(ret); |
3039 | 3175 | ||
3040 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
3176 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); |
3041 | if (IS_ERR(fb)) { |
3177 | if (IS_ERR(fb)) { |
3042 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
3178 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
Line 3043... | Line -... | ||
3043 | return fb; |
- | |
3044 | } |
- | |
3045 | - | ||
3046 | mutex_lock(&file_priv->fbs_lock); |
- | |
3047 | r->fb_id = fb->base.id; |
- | |
3048 | list_add(&fb->filp_head, &file_priv->fbs); |
- | |
3049 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
3179 | return fb; |
3050 | mutex_unlock(&file_priv->fbs_lock); |
3180 | } |
Line 3051... | Line 3181... | ||
3051 | 3181 | ||
3052 | return fb; |
3182 | return fb; |
Line 3068... | Line 3198... | ||
3068 | * Zero on success, negative errno on failure. |
3198 | * Zero on success, negative errno on failure. |
3069 | */ |
3199 | */ |
3070 | int drm_mode_addfb2(struct drm_device *dev, |
3200 | int drm_mode_addfb2(struct drm_device *dev, |
3071 | void *data, struct drm_file *file_priv) |
3201 | void *data, struct drm_file *file_priv) |
3072 | { |
3202 | { |
- | 3203 | struct drm_mode_fb_cmd2 *r = data; |
|
3073 | struct drm_framebuffer *fb; |
3204 | struct drm_framebuffer *fb; |
Line 3074... | Line 3205... | ||
3074 | 3205 | ||
3075 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3206 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 3076... | Line 3207... | ||
3076 | return -EINVAL; |
3207 | return -EINVAL; |
3077 | 3208 | ||
3078 | fb = add_framebuffer_internal(dev, data, file_priv); |
3209 | fb = internal_framebuffer_create(dev, r, file_priv); |
Line -... | Line 3210... | ||
- | 3210 | if (IS_ERR(fb)) |
|
- | 3211 | return PTR_ERR(fb); |
|
- | 3212 | ||
- | 3213 | /* Transfer ownership to the filp for reaping on close */ |
|
- | 3214 | ||
- | 3215 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
|
- | 3216 | mutex_lock(&file_priv->fbs_lock); |
|
- | 3217 | r->fb_id = fb->base.id; |
|
3079 | if (IS_ERR(fb)) |
3218 | list_add(&fb->filp_head, &file_priv->fbs); |
3080 | return PTR_ERR(fb); |
3219 | mutex_unlock(&file_priv->fbs_lock); |
Line 3081... | Line 3220... | ||
3081 | 3220 | ||
3082 | return 0; |
3221 | return 0; |
Line 3116... | Line 3255... | ||
3116 | if (fb == fbl) |
3255 | if (fb == fbl) |
3117 | found = 1; |
3256 | found = 1; |
3118 | if (!found) |
3257 | if (!found) |
3119 | goto fail_lookup; |
3258 | goto fail_lookup; |
Line 3120... | Line -... | ||
3120 | - | ||
3121 | /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ |
- | |
3122 | __drm_framebuffer_unregister(dev, fb); |
- | |
3123 | 3259 | ||
3124 | list_del_init(&fb->filp_head); |
3260 | list_del_init(&fb->filp_head); |
3125 | mutex_unlock(&dev->mode_config.fb_lock); |
3261 | mutex_unlock(&dev->mode_config.fb_lock); |
Line 3126... | Line 3262... | ||
3126 | mutex_unlock(&file_priv->fbs_lock); |
3262 | mutex_unlock(&file_priv->fbs_lock); |
Line 3127... | Line 3263... | ||
3127 | 3263 | ||
Line 3128... | Line 3264... | ||
3128 | drm_framebuffer_remove(fb); |
3264 | drm_framebuffer_unreference(fb); |
3129 | 3265 | ||
Line 3247... | Line 3383... | ||
3247 | if (num_clips && clips_ptr) { |
3383 | if (num_clips && clips_ptr) { |
3248 | if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { |
3384 | if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { |
3249 | ret = -EINVAL; |
3385 | ret = -EINVAL; |
3250 | goto out_err1; |
3386 | goto out_err1; |
3251 | } |
3387 | } |
3252 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); |
3388 | clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); |
3253 | if (!clips) { |
3389 | if (!clips) { |
3254 | ret = -ENOMEM; |
3390 | ret = -ENOMEM; |
3255 | goto out_err1; |
3391 | goto out_err1; |
3256 | } |
3392 | } |
Line 3290... | Line 3426... | ||
3290 | * Returns: |
3426 | * Returns: |
3291 | * Zero on success, negative errno on failure. |
3427 | * Zero on success, negative errno on failure. |
3292 | */ |
3428 | */ |
3293 | void drm_fb_release(struct drm_file *priv) |
3429 | void drm_fb_release(struct drm_file *priv) |
3294 | { |
3430 | { |
3295 | struct drm_device *dev = priv->minor->dev; |
- | |
3296 | struct drm_framebuffer *fb, *tfb; |
3431 | struct drm_framebuffer *fb, *tfb; |
Line 3297... | Line 3432... | ||
3297 | 3432 | ||
3298 | /* |
3433 | /* |
3299 | * When the file gets released that means no one else can access the fb |
3434 | * When the file gets released that means no one else can access the fb |
Line 3304... | Line 3439... | ||
3304 | * Note that a real deadlock between fpriv->fbs_lock and the modeset |
3439 | * Note that a real deadlock between fpriv->fbs_lock and the modeset |
3305 | * locks is impossible here since no one else but this function can get |
3440 | * locks is impossible here since no one else but this function can get |
3306 | * at it any more. |
3441 | * at it any more. |
3307 | */ |
3442 | */ |
3308 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
3443 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
3309 | - | ||
3310 | mutex_lock(&dev->mode_config.fb_lock); |
- | |
3311 | /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ |
- | |
3312 | __drm_framebuffer_unregister(dev, fb); |
- | |
3313 | mutex_unlock(&dev->mode_config.fb_lock); |
- | |
3314 | - | ||
3315 | list_del_init(&fb->filp_head); |
3444 | list_del_init(&fb->filp_head); |
Line 3316... | Line 3445... | ||
3316 | 3445 | ||
3317 | /* This will also drop the fpriv->fbs reference. */ |
3446 | /* This drops the fpriv->fbs reference. */ |
3318 | drm_framebuffer_remove(fb); |
3447 | drm_framebuffer_unreference(fb); |
3319 | } |
3448 | } |
3320 | } |
3449 | } |
Line 3350... | Line 3479... | ||
3350 | return NULL; |
3479 | return NULL; |
Line 3351... | Line 3480... | ||
3351 | 3480 | ||
Line 3352... | Line 3481... | ||
3352 | property->dev = dev; |
3481 | property->dev = dev; |
3353 | 3482 | ||
- | 3483 | if (num_values) { |
|
3354 | if (num_values) { |
3484 | property->values = kcalloc(num_values, sizeof(uint64_t), |
3355 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); |
3485 | GFP_KERNEL); |
3356 | if (!property->values) |
3486 | if (!property->values) |
Line 3357... | Line 3487... | ||
3357 | goto fail; |
3487 | goto fail; |
Line 3499... | Line 3629... | ||
3499 | 3629 | ||
3500 | return property; |
3630 | return property; |
Line 3501... | Line 3631... | ||
3501 | } |
3631 | } |
3502 | 3632 | ||
3503 | /** |
3633 | /** |
3504 | * drm_property_create_range - create a new ranged property type |
3634 | * drm_property_create_range - create a new unsigned ranged property type |
3505 | * @dev: drm device |
3635 | * @dev: drm device |
3506 | * @flags: flags specifying the property type |
3636 | * @flags: flags specifying the property type |
3507 | * @name: name of the property |
3637 | * @name: name of the property |
3508 | * @min: minimum value of the property |
3638 | * @min: minimum value of the property |
3509 | * @max: maximum value of the property |
3639 | * @max: maximum value of the property |
3510 | * |
3640 | * |
3511 | * This creates a new generic drm property which can then be attached to a drm |
3641 | * This creates a new generic drm property which can then be attached to a drm |
3512 | * object with drm_object_attach_property. The returned property object must be |
3642 | * object with drm_object_attach_property. The returned property object must be |
3513 | * freed with drm_property_destroy. |
3643 | * freed with drm_property_destroy. |
3514 | * |
3644 | * |
3515 | * Userspace is allowed to set any integer value in the (min, max) range |
3645 | * Userspace is allowed to set any unsigned integer value in the (min, max) |
3516 | * inclusive. |
3646 | * range inclusive. |
3517 | * |
3647 | * |
3518 | * Returns: |
3648 | * Returns: |
3519 | * A pointer to the newly created property on success, NULL on failure. |
3649 | * A pointer to the newly created property on success, NULL on failure. |
Line 3525... | Line 3655... | ||
3525 | return property_create_range(dev, DRM_MODE_PROP_RANGE | flags, |
3655 | return property_create_range(dev, DRM_MODE_PROP_RANGE | flags, |
3526 | name, min, max); |
3656 | name, min, max); |
3527 | } |
3657 | } |
3528 | EXPORT_SYMBOL(drm_property_create_range); |
3658 | EXPORT_SYMBOL(drm_property_create_range); |
Line -... | Line 3659... | ||
- | 3659 | ||
- | 3660 | /** |
|
- | 3661 | * drm_property_create_signed_range - create a new signed ranged property type |
|
- | 3662 | * @dev: drm device |
|
- | 3663 | * @flags: flags specifying the property type |
|
- | 3664 | * @name: name of the property |
|
- | 3665 | * @min: minimum value of the property |
|
- | 3666 | * @max: maximum value of the property |
|
- | 3667 | * |
|
- | 3668 | * This creates a new generic drm property which can then be attached to a drm |
|
- | 3669 | * object with drm_object_attach_property. The returned property object must be |
|
- | 3670 | * freed with drm_property_destroy. |
|
- | 3671 | * |
|
- | 3672 | * Userspace is allowed to set any signed integer value in the (min, max) |
|
- | 3673 | * range inclusive. |
|
- | 3674 | * |
|
- | 3675 | * Returns: |
|
- | 3676 | * A pointer to the newly created property on success, NULL on failure. |
|
3529 | 3677 | */ |
|
3530 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, |
3678 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, |
3531 | int flags, const char *name, |
3679 | int flags, const char *name, |
3532 | int64_t min, int64_t max) |
3680 | int64_t min, int64_t max) |
3533 | { |
3681 | { |
3534 | return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags, |
3682 | return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags, |
3535 | name, I642U64(min), I642U64(max)); |
3683 | name, I642U64(min), I642U64(max)); |
3536 | } |
3684 | } |
Line -... | Line 3685... | ||
- | 3685 | EXPORT_SYMBOL(drm_property_create_signed_range); |
|
- | 3686 | ||
- | 3687 | /** |
|
- | 3688 | * drm_property_create_object - create a new object property type |
|
- | 3689 | * @dev: drm device |
|
- | 3690 | * @flags: flags specifying the property type |
|
- | 3691 | * @name: name of the property |
|
- | 3692 | * @type: object type from DRM_MODE_OBJECT_* defines |
|
- | 3693 | * |
|
- | 3694 | * This creates a new generic drm property which can then be attached to a drm |
|
- | 3695 | * object with drm_object_attach_property. The returned property object must be |
|
- | 3696 | * freed with drm_property_destroy. |
|
- | 3697 | * |
|
- | 3698 | * Userspace is only allowed to set this to any property value of the given |
|
- | 3699 | * @type. Only useful for atomic properties, which is enforced. |
|
- | 3700 | * |
|
- | 3701 | * Returns: |
|
3537 | EXPORT_SYMBOL(drm_property_create_signed_range); |
3702 | * A pointer to the newly created property on success, NULL on failure. |
3538 | 3703 | */ |
|
3539 | struct drm_property *drm_property_create_object(struct drm_device *dev, |
3704 | struct drm_property *drm_property_create_object(struct drm_device *dev, |
3540 | int flags, const char *name, uint32_t type) |
3705 | int flags, const char *name, uint32_t type) |
Line 3541... | Line 3706... | ||
3541 | { |
3706 | { |
Line -... | Line 3707... | ||
- | 3707 | struct drm_property *property; |
|
- | 3708 | ||
- | 3709 | flags |= DRM_MODE_PROP_OBJECT; |
|
3542 | struct drm_property *property; |
3710 | |
3543 | 3711 | if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC))) |
|
3544 | flags |= DRM_MODE_PROP_OBJECT; |
3712 | return NULL; |
Line 3545... | Line 3713... | ||
3545 | 3713 | ||
Line 3552... | Line 3720... | ||
3552 | return property; |
3720 | return property; |
3553 | } |
3721 | } |
3554 | EXPORT_SYMBOL(drm_property_create_object); |
3722 | EXPORT_SYMBOL(drm_property_create_object); |
Line 3555... | Line 3723... | ||
3555 | 3723 | ||
- | 3724 | /** |
|
- | 3725 | * drm_property_create_bool - create a new boolean property type |
|
- | 3726 | * @dev: drm device |
|
- | 3727 | * @flags: flags specifying the property type |
|
- | 3728 | * @name: name of the property |
|
- | 3729 | * |
|
- | 3730 | * This creates a new generic drm property which can then be attached to a drm |
|
- | 3731 | * object with drm_object_attach_property. The returned property object must be |
|
- | 3732 | * freed with drm_property_destroy. |
|
- | 3733 | * |
|
- | 3734 | * This is implemented as a ranged property with only {0, 1} as valid values. |
|
- | 3735 | * |
|
- | 3736 | * Returns: |
|
- | 3737 | * A pointer to the newly created property on success, NULL on failure. |
|
- | 3738 | */ |
|
- | 3739 | struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags, |
|
- | 3740 | const char *name) |
|
- | 3741 | { |
|
- | 3742 | return drm_property_create_range(dev, flags, name, 0, 1); |
|
- | 3743 | } |
|
- | 3744 | EXPORT_SYMBOL(drm_property_create_bool); |
|
- | 3745 | ||
3556 | /** |
3746 | /** |
3557 | * drm_property_add_enum - add a possible value to an enumeration property |
3747 | * drm_property_add_enum - add a possible value to an enumeration property |
3558 | * @property: enumeration property to change |
3748 | * @property: enumeration property to change |
3559 | * @index: index of the new enumeration |
3749 | * @index: index of the new enumeration |
3560 | * @value: value of the new enumeration |
3750 | * @value: value of the new enumeration |
Line 3656... | Line 3846... | ||
3656 | "you see this message on the same object type.\n", |
3846 | "you see this message on the same object type.\n", |
3657 | obj->type); |
3847 | obj->type); |
3658 | return; |
3848 | return; |
3659 | } |
3849 | } |
Line 3660... | Line 3850... | ||
3660 | 3850 | ||
3661 | obj->properties->ids[count] = property->base.id; |
3851 | obj->properties->properties[count] = property; |
3662 | obj->properties->values[count] = init_val; |
3852 | obj->properties->values[count] = init_val; |
- | 3853 | obj->properties->count++; |
|
- | 3854 | if (property->flags & DRM_MODE_PROP_ATOMIC) |
|
3663 | obj->properties->count++; |
3855 | obj->properties->atomic_count++; |
3664 | } |
3856 | } |
Line 3665... | Line 3857... | ||
3665 | EXPORT_SYMBOL(drm_object_attach_property); |
3857 | EXPORT_SYMBOL(drm_object_attach_property); |
3666 | 3858 | ||
Line 3681... | Line 3873... | ||
3681 | struct drm_property *property, uint64_t val) |
3873 | struct drm_property *property, uint64_t val) |
3682 | { |
3874 | { |
3683 | int i; |
3875 | int i; |
Line 3684... | Line 3876... | ||
3684 | 3876 | ||
3685 | for (i = 0; i < obj->properties->count; i++) { |
3877 | for (i = 0; i < obj->properties->count; i++) { |
3686 | if (obj->properties->ids[i] == property->base.id) { |
3878 | if (obj->properties->properties[i] == property) { |
3687 | obj->properties->values[i] = val; |
3879 | obj->properties->values[i] = val; |
3688 | return 0; |
3880 | return 0; |
3689 | } |
3881 | } |
Line 3710... | Line 3902... | ||
3710 | int drm_object_property_get_value(struct drm_mode_object *obj, |
3902 | int drm_object_property_get_value(struct drm_mode_object *obj, |
3711 | struct drm_property *property, uint64_t *val) |
3903 | struct drm_property *property, uint64_t *val) |
3712 | { |
3904 | { |
3713 | int i; |
3905 | int i; |
Line -... | Line 3906... | ||
- | 3906 | ||
- | 3907 | /* read-only properties bypass atomic mechanism and still store |
|
- | 3908 | * their value in obj->properties->values[].. mostly to avoid |
|
- | 3909 | * having to deal w/ EDID and similar props in atomic paths: |
|
- | 3910 | */ |
|
- | 3911 | if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) && |
|
- | 3912 | !(property->flags & DRM_MODE_PROP_IMMUTABLE)) |
|
- | 3913 | return drm_atomic_get_property(obj, property, val); |
|
3714 | 3914 | ||
3715 | for (i = 0; i < obj->properties->count; i++) { |
3915 | for (i = 0; i < obj->properties->count; i++) { |
3716 | if (obj->properties->ids[i] == property->base.id) { |
3916 | if (obj->properties->properties[i] == property) { |
3717 | *val = obj->properties->values[i]; |
3917 | *val = obj->properties->values[i]; |
3718 | return 0; |
3918 | return 0; |
3719 | } |
3919 | } |
Line 3823... | Line 4023... | ||
3823 | drm_modeset_unlock_all(dev); |
4023 | drm_modeset_unlock_all(dev); |
3824 | return ret; |
4024 | return ret; |
3825 | } |
4025 | } |
3826 | #endif |
4026 | #endif |
Line -... | Line 4027... | ||
- | 4027 | ||
- | 4028 | /** |
|
- | 4029 | * drm_property_create_blob - Create new blob property |
|
- | 4030 | * |
|
- | 4031 | * Creates a new blob property for a specified DRM device, optionally |
|
- | 4032 | * copying data. |
|
- | 4033 | * |
|
- | 4034 | * @dev: DRM device to create property for |
|
- | 4035 | * @length: Length to allocate for blob data |
|
- | 4036 | * @data: If specified, copies data into blob |
|
- | 4037 | * |
|
- | 4038 | * Returns: |
|
- | 4039 | * New blob property with a single reference on success, or an ERR_PTR |
|
- | 4040 | * value on failure. |
|
3827 | 4041 | */ |
|
3828 | static struct drm_property_blob * |
4042 | struct drm_property_blob * |
3829 | drm_property_create_blob(struct drm_device *dev, size_t length, |
4043 | drm_property_create_blob(struct drm_device *dev, size_t length, |
3830 | const void *data) |
4044 | const void *data) |
3831 | { |
4045 | { |
3832 | struct drm_property_blob *blob; |
4046 | struct drm_property_blob *blob; |
Line 3833... | Line 4047... | ||
3833 | int ret; |
4047 | int ret; |
3834 | 4048 | ||
Line 3835... | Line 4049... | ||
3835 | if (!length || !data) |
4049 | if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob)) |
3836 | return NULL; |
4050 | return ERR_PTR(-EINVAL); |
3837 | 4051 | ||
- | 4052 | blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); |
|
- | 4053 | if (!blob) |
|
- | 4054 | return ERR_PTR(-ENOMEM); |
|
- | 4055 | ||
- | 4056 | /* This must be explicitly initialised, so we can safely call list_del |
|
- | 4057 | * on it in the removal handler, even if it isn't in a file list. */ |
|
- | 4058 | INIT_LIST_HEAD(&blob->head_file); |
|
- | 4059 | blob->length = length; |
|
- | 4060 | blob->dev = dev; |
|
- | 4061 | ||
- | 4062 | if (data) |
|
Line 3838... | Line 4063... | ||
3838 | blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); |
4063 | memcpy(blob->data, data, length); |
3839 | if (!blob) |
4064 | |
3840 | return NULL; |
4065 | mutex_lock(&dev->mode_config.blob_lock); |
- | 4066 | ||
3841 | 4067 | ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); |
|
3842 | ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); |
4068 | if (ret) { |
Line 3843... | Line 4069... | ||
3843 | if (ret) { |
4069 | kfree(blob); |
Line -... | Line 4070... | ||
- | 4070 | mutex_unlock(&dev->mode_config.blob_lock); |
|
- | 4071 | return ERR_PTR(-EINVAL); |
|
- | 4072 | } |
|
3844 | kfree(blob); |
4073 | |
Line 3845... | Line -... | ||
3845 | return NULL; |
- | |
3846 | } |
4074 | kref_init(&blob->refcount); |
3847 | 4075 | ||
- | 4076 | list_add_tail(&blob->head_global, |
|
Line -... | Line 4077... | ||
- | 4077 | &dev->mode_config.property_blob_list); |
|
3848 | blob->length = length; |
4078 | |
- | 4079 | mutex_unlock(&dev->mode_config.blob_lock); |
|
- | 4080 | ||
- | 4081 | return blob; |
|
- | 4082 | } |
|
- | 4083 | EXPORT_SYMBOL(drm_property_create_blob); |
|
3849 | 4084 | ||
3850 | memcpy(blob->data, data, length); |
4085 | /** |
3851 | 4086 | * drm_property_free_blob - Blob property destructor |
|
- | 4087 | * |
|
- | 4088 | * Internal free function for blob properties; must not be used directly. |
|
- | 4089 | * |
|
- | 4090 | * @kref: Reference |
|
- | 4091 | */ |
|
3852 | list_add_tail(&blob->head, &dev->mode_config.property_blob_list); |
4092 | static void drm_property_free_blob(struct kref *kref) |
- | 4093 | { |
|
- | 4094 | struct drm_property_blob *blob = |
|
3853 | return blob; |
4095 | container_of(kref, struct drm_property_blob, refcount); |
3854 | } |
4096 | |
Line -... | Line 4097... | ||
- | 4097 | WARN_ON(!mutex_is_locked(&blob->dev->mode_config.blob_lock)); |
|
- | 4098 | ||
- | 4099 | list_del(&blob->head_global); |
|
- | 4100 | list_del(&blob->head_file); |
|
- | 4101 | drm_mode_object_put(blob->dev, &blob->base); |
|
- | 4102 | ||
- | 4103 | kfree(blob); |
|
- | 4104 | } |
|
- | 4105 | ||
- | 4106 | /** |
|
- | 4107 | * drm_property_unreference_blob - Unreference a blob property |
|
- | 4108 | * |
|
- | 4109 | * Drop a reference on a blob property. May free the object. |
|
- | 4110 | * |
|
- | 4111 | * @blob: Pointer to blob property |
|
- | 4112 | */ |
|
- | 4113 | void drm_property_unreference_blob(struct drm_property_blob *blob) |
|
- | 4114 | { |
|
- | 4115 | struct drm_device *dev; |
|
- | 4116 | ||
- | 4117 | if (!blob) |
|
- | 4118 | return; |
|
- | 4119 | ||
- | 4120 | dev = blob->dev; |
|
- | 4121 | ||
- | 4122 | DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount)); |
|
- | 4123 | ||
- | 4124 | if (kref_put_mutex(&blob->refcount, drm_property_free_blob, |
|
- | 4125 | &dev->mode_config.blob_lock)) |
|
- | 4126 | mutex_unlock(&dev->mode_config.blob_lock); |
|
- | 4127 | else |
|
- | 4128 | might_lock(&dev->mode_config.blob_lock); |
|
- | 4129 | } |
|
- | 4130 | EXPORT_SYMBOL(drm_property_unreference_blob); |
|
- | 4131 | ||
- | 4132 | /** |
|
- | 4133 | * drm_property_unreference_blob_locked - Unreference a blob property with blob_lock held |
|
- | 4134 | * |
|
- | 4135 | * Drop a reference on a blob property. May free the object. This must be |
|
- | 4136 | * called with blob_lock held. |
|
- | 4137 | * |
|
- | 4138 | * @blob: Pointer to blob property |
|
- | 4139 | */ |
|
- | 4140 | static void drm_property_unreference_blob_locked(struct drm_property_blob *blob) |
|
- | 4141 | { |
|
- | 4142 | if (!blob) |
|
- | 4143 | return; |
|
- | 4144 | ||
- | 4145 | DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount)); |
|
- | 4146 | ||
- | 4147 | kref_put(&blob->refcount, drm_property_free_blob); |
|
- | 4148 | } |
|
- | 4149 | ||
- | 4150 | /** |
|
- | 4151 | * drm_property_destroy_user_blobs - destroy all blobs created by this client |
|
- | 4152 | * @dev: DRM device |
|
- | 4153 | * @file_priv: destroy all blobs owned by this file handle |
|
- | 4154 | */ |
|
- | 4155 | void drm_property_destroy_user_blobs(struct drm_device *dev, |
|
- | 4156 | struct drm_file *file_priv) |
|
- | 4157 | { |
|
- | 4158 | struct drm_property_blob *blob, *bt; |
|
- | 4159 | ||
- | 4160 | mutex_lock(&dev->mode_config.blob_lock); |
|
- | 4161 | ||
- | 4162 | list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) { |
|
- | 4163 | list_del_init(&blob->head_file); |
|
- | 4164 | drm_property_unreference_blob_locked(blob); |
|
- | 4165 | } |
|
- | 4166 | ||
- | 4167 | mutex_unlock(&dev->mode_config.blob_lock); |
|
- | 4168 | } |
|
- | 4169 | ||
- | 4170 | /** |
|
- | 4171 | * drm_property_reference_blob - Take a reference on an existing property |
|
- | 4172 | * |
|
- | 4173 | * Take a new reference on an existing blob property. |
|
- | 4174 | * |
|
- | 4175 | * @blob: Pointer to blob property |
|
- | 4176 | */ |
|
- | 4177 | struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob) |
|
- | 4178 | { |
|
- | 4179 | DRM_DEBUG("%p: blob ID: %d (%d)\n", blob, blob->base.id, atomic_read(&blob->refcount.refcount)); |
|
- | 4180 | kref_get(&blob->refcount); |
|
- | 4181 | return blob; |
|
- | 4182 | } |
|
- | 4183 | EXPORT_SYMBOL(drm_property_reference_blob); |
|
- | 4184 | ||
- | 4185 | /* |
|
- | 4186 | * Like drm_property_lookup_blob, but does not return an additional reference. |
|
- | 4187 | * Must be called with blob_lock held. |
|
- | 4188 | */ |
|
- | 4189 | static struct drm_property_blob *__drm_property_lookup_blob(struct drm_device *dev, |
|
- | 4190 | uint32_t id) |
|
- | 4191 | { |
|
- | 4192 | struct drm_mode_object *obj = NULL; |
|
- | 4193 | struct drm_property_blob *blob; |
|
- | 4194 | ||
- | 4195 | WARN_ON(!mutex_is_locked(&dev->mode_config.blob_lock)); |
|
- | 4196 | ||
- | 4197 | mutex_lock(&dev->mode_config.idr_mutex); |
|
- | 4198 | obj = idr_find(&dev->mode_config.crtc_idr, id); |
|
- | 4199 | if (!obj || (obj->type != DRM_MODE_OBJECT_BLOB) || (obj->id != id)) |
|
- | 4200 | blob = NULL; |
|
- | 4201 | else |
|
- | 4202 | blob = obj_to_blob(obj); |
|
- | 4203 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
- | 4204 | ||
- | 4205 | return blob; |
|
- | 4206 | } |
|
- | 4207 | ||
- | 4208 | /** |
|
- | 4209 | * drm_property_lookup_blob - look up a blob property and take a reference |
|
- | 4210 | * @dev: drm device |
|
- | 4211 | * @id: id of the blob property |
|
- | 4212 | * |
|
- | 4213 | * If successful, this takes an additional reference to the blob property. |
|
- | 4214 | * callers need to make sure to eventually unreference the returned property |
|
- | 4215 | * again, using @drm_property_unreference_blob. |
|
- | 4216 | */ |
|
- | 4217 | struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, |
|
- | 4218 | uint32_t id) |
|
- | 4219 | { |
|
- | 4220 | struct drm_property_blob *blob; |
|
- | 4221 | ||
- | 4222 | mutex_lock(&dev->mode_config.blob_lock); |
|
- | 4223 | blob = __drm_property_lookup_blob(dev, id); |
|
- | 4224 | if (blob) { |
|
- | 4225 | if (!kref_get_unless_zero(&blob->refcount)) |
|
- | 4226 | blob = NULL; |
|
- | 4227 | } |
|
- | 4228 | mutex_unlock(&dev->mode_config.blob_lock); |
|
- | 4229 | ||
- | 4230 | return blob; |
|
- | 4231 | } |
|
- | 4232 | EXPORT_SYMBOL(drm_property_lookup_blob); |
|
- | 4233 | ||
- | 4234 | /** |
|
- | 4235 | * drm_property_replace_global_blob - atomically replace existing blob property |
|
- | 4236 | * @dev: drm device |
|
- | 4237 | * @replace: location of blob property pointer to be replaced |
|
- | 4238 | * @length: length of data for new blob, or 0 for no data |
|
- | 4239 | * @data: content for new blob, or NULL for no data |
|
- | 4240 | * @obj_holds_id: optional object for property holding blob ID |
|
- | 4241 | * @prop_holds_id: optional property holding blob ID |
|
- | 4242 | * @return 0 on success or error on failure |
|
- | 4243 | * |
|
- | 4244 | * This function will atomically replace a global property in the blob list, |
|
- | 4245 | * optionally updating a property which holds the ID of that property. It is |
|
- | 4246 | * guaranteed to be atomic: no caller will be allowed to see intermediate |
|
- | 4247 | * results, and either the entire operation will succeed and clean up the |
|
- | 4248 | * previous property, or it will fail and the state will be unchanged. |
|
- | 4249 | * |
|
- | 4250 | * If length is 0 or data is NULL, no new blob will be created, and the holding |
|
- | 4251 | * property, if specified, will be set to 0. |
|
- | 4252 | * |
|
- | 4253 | * Access to the replace pointer is assumed to be protected by the caller, e.g. |
|
- | 4254 | * by holding the relevant modesetting object lock for its parent. |
|
- | 4255 | * |
|
- | 4256 | * For example, a drm_connector has a 'PATH' property, which contains the ID |
|
- | 4257 | * of a blob property with the value of the MST path information. Calling this |
|
- | 4258 | * function with replace pointing to the connector's path_blob_ptr, length and |
|
- | 4259 | * data set for the new path information, obj_holds_id set to the connector's |
|
- | 4260 | * base object, and prop_holds_id set to the path property name, will perform |
|
- | 4261 | * a completely atomic update. The access to path_blob_ptr is protected by the |
|
- | 4262 | * caller holding a lock on the connector. |
|
- | 4263 | */ |
|
- | 4264 | static int drm_property_replace_global_blob(struct drm_device *dev, |
|
- | 4265 | struct drm_property_blob **replace, |
|
- | 4266 | size_t length, |
|
- | 4267 | const void *data, |
|
- | 4268 | struct drm_mode_object *obj_holds_id, |
|
- | 4269 | struct drm_property *prop_holds_id) |
|
- | 4270 | { |
|
- | 4271 | struct drm_property_blob *new_blob = NULL; |
|
- | 4272 | struct drm_property_blob *old_blob = NULL; |
|
- | 4273 | int ret; |
|
- | 4274 | ||
- | 4275 | WARN_ON(replace == NULL); |
|
- | 4276 | ||
- | 4277 | old_blob = *replace; |
|
- | 4278 | ||
- | 4279 | if (length && data) { |
|
- | 4280 | new_blob = drm_property_create_blob(dev, length, data); |
|
- | 4281 | if (IS_ERR(new_blob)) |
|
- | 4282 | return PTR_ERR(new_blob); |
|
- | 4283 | } |
|
- | 4284 | ||
- | 4285 | /* This does not need to be synchronised with blob_lock, as the |
|
- | 4286 | * get_properties ioctl locks all modesetting objects, and |
|
- | 4287 | * obj_holds_id must be locked before calling here, so we cannot |
|
- | 4288 | * have its value out of sync with the list membership modified |
|
- | 4289 | * below under blob_lock. */ |
|
- | 4290 | if (obj_holds_id) { |
|
- | 4291 | ret = drm_object_property_set_value(obj_holds_id, |
|
- | 4292 | prop_holds_id, |
|
- | 4293 | new_blob ? |
|
- | 4294 | new_blob->base.id : 0); |
|
- | 4295 | if (ret != 0) |
|
- | 4296 | goto err_created; |
|
- | 4297 | } |
|
- | 4298 | ||
- | 4299 | drm_property_unreference_blob(old_blob); |
|
- | 4300 | *replace = new_blob; |
|
3855 | 4301 | ||
3856 | static void drm_property_destroy_blob(struct drm_device *dev, |
4302 | return 0; |
3857 | struct drm_property_blob *blob) |
4303 | |
3858 | { |
4304 | err_created: |
3859 | drm_mode_object_put(dev, &blob->base); |
4305 | drm_property_unreference_blob(new_blob); |
Line 3886... | Line 4332... | ||
3886 | 4332 | ||
3887 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4333 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 3888... | Line 4334... | ||
3888 | return -EINVAL; |
4334 | return -EINVAL; |
- | 4335 | ||
3889 | 4336 | drm_modeset_lock_all(dev); |
|
3890 | drm_modeset_lock_all(dev); |
4337 | mutex_lock(&dev->mode_config.blob_lock); |
3891 | blob = drm_property_blob_find(dev, out_resp->blob_id); |
4338 | blob = __drm_property_lookup_blob(dev, out_resp->blob_id); |
3892 | if (!blob) { |
4339 | if (!blob) { |
3893 | ret = -ENOENT; |
4340 | ret = -ENOENT; |
Line 3902... | Line 4349... | ||
3902 | } |
4349 | } |
3903 | } |
4350 | } |
3904 | out_resp->length = blob->length; |
4351 | out_resp->length = blob->length; |
Line 3905... | Line 4352... | ||
3905 | 4352 | ||
- | 4353 | done: |
|
3906 | done: |
4354 | mutex_unlock(&dev->mode_config.blob_lock); |
3907 | drm_modeset_unlock_all(dev); |
4355 | drm_modeset_unlock_all(dev); |
3908 | return ret; |
4356 | return ret; |
3909 | } |
4357 | } |
Line 3910... | Line 4358... | ||
3910 | #endif |
4358 | #endif |
3911 | 4359 | ||
3912 | /** |
4360 | /** |
3913 | * drm_mode_connector_set_path_property - set tile property on connector |
4361 | * drm_mode_connector_set_path_property - set tile property on connector |
3914 | * @connector: connector to set property on. |
4362 | * @connector: connector to set property on. |
3915 | * @path: path to use for property. |
4363 | * @path: path to use for property; must not be NULL. |
3916 | * |
4364 | * |
3917 | * This creates a property to expose to userspace to specify a |
4365 | * This creates a property to expose to userspace to specify a |
3918 | * connector path. This is mainly used for DisplayPort MST where |
4366 | * connector path. This is mainly used for DisplayPort MST where |
Line 3924... | Line 4372... | ||
3924 | */ |
4372 | */ |
3925 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
4373 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
3926 | const char *path) |
4374 | const char *path) |
3927 | { |
4375 | { |
3928 | struct drm_device *dev = connector->dev; |
4376 | struct drm_device *dev = connector->dev; |
3929 | size_t size = strlen(path) + 1; |
- | |
3930 | int ret; |
4377 | int ret; |
Line 3931... | Line 4378... | ||
3931 | 4378 | ||
3932 | connector->path_blob_ptr = drm_property_create_blob(connector->dev, |
4379 | ret = drm_property_replace_global_blob(dev, |
3933 | size, path); |
4380 | &connector->path_blob_ptr, |
3934 | if (!connector->path_blob_ptr) |
4381 | strlen(path) + 1, |
3935 | return -EINVAL; |
- | |
3936 | 4382 | path, |
|
3937 | ret = drm_object_property_set_value(&connector->base, |
4383 | &connector->base, |
3938 | dev->mode_config.path_property, |
- | |
3939 | connector->path_blob_ptr->base.id); |
4384 | dev->mode_config.path_property); |
3940 | return ret; |
4385 | return ret; |
3941 | } |
4386 | } |
Line 3942... | Line 4387... | ||
3942 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); |
4387 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); |
Line 3953... | Line 4398... | ||
3953 | * Zero on success, errno on failure. |
4398 | * Zero on success, errno on failure. |
3954 | */ |
4399 | */ |
3955 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) |
4400 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) |
3956 | { |
4401 | { |
3957 | struct drm_device *dev = connector->dev; |
4402 | struct drm_device *dev = connector->dev; |
3958 | int ret, size; |
- | |
3959 | char tile[256]; |
4403 | char tile[256]; |
3960 | - | ||
3961 | if (connector->tile_blob_ptr) |
4404 | int ret; |
3962 | drm_property_destroy_blob(dev, connector->tile_blob_ptr); |
- | |
Line 3963... | Line 4405... | ||
3963 | 4405 | ||
3964 | if (!connector->has_tile) { |
4406 | if (!connector->has_tile) { |
- | 4407 | ret = drm_property_replace_global_blob(dev, |
|
- | 4408 | &connector->tile_blob_ptr, |
|
- | 4409 | 0, |
|
3965 | connector->tile_blob_ptr = NULL; |
4410 | NULL, |
3966 | ret = drm_object_property_set_value(&connector->base, |
4411 | &connector->base, |
3967 | dev->mode_config.tile_property, 0); |
4412 | dev->mode_config.tile_property); |
3968 | return ret; |
4413 | return ret; |
Line 3969... | Line 4414... | ||
3969 | } |
4414 | } |
3970 | 4415 | ||
3971 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", |
4416 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", |
3972 | connector->tile_group->id, connector->tile_is_single_monitor, |
4417 | connector->tile_group->id, connector->tile_is_single_monitor, |
3973 | connector->num_h_tile, connector->num_v_tile, |
4418 | connector->num_h_tile, connector->num_v_tile, |
3974 | connector->tile_h_loc, connector->tile_v_loc, |
- | |
Line 3975... | Line 4419... | ||
3975 | connector->tile_h_size, connector->tile_v_size); |
4419 | connector->tile_h_loc, connector->tile_v_loc, |
3976 | size = strlen(tile) + 1; |
4420 | connector->tile_h_size, connector->tile_v_size); |
3977 | 4421 | ||
3978 | connector->tile_blob_ptr = drm_property_create_blob(connector->dev, |
4422 | ret = drm_property_replace_global_blob(dev, |
3979 | size, tile); |
- | |
3980 | if (!connector->tile_blob_ptr) |
4423 | &connector->tile_blob_ptr, |
3981 | return -EINVAL; |
4424 | strlen(tile) + 1, |
3982 | - | ||
3983 | ret = drm_object_property_set_value(&connector->base, |
4425 | tile, |
3984 | dev->mode_config.tile_property, |
4426 | &connector->base, |
3985 | connector->tile_blob_ptr->base.id); |
4427 | dev->mode_config.tile_property); |
Line 3986... | Line 4428... | ||
3986 | return ret; |
4428 | return ret; |
Line 4000... | Line 4442... | ||
4000 | */ |
4442 | */ |
4001 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
4443 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
4002 | const struct edid *edid) |
4444 | const struct edid *edid) |
4003 | { |
4445 | { |
4004 | struct drm_device *dev = connector->dev; |
4446 | struct drm_device *dev = connector->dev; |
4005 | size_t size; |
4447 | size_t size = 0; |
4006 | int ret; |
4448 | int ret; |
Line 4007... | Line 4449... | ||
4007 | 4449 | ||
4008 | /* ignore requests to set edid when overridden */ |
4450 | /* ignore requests to set edid when overridden */ |
4009 | if (connector->override_edid) |
4451 | if (connector->override_edid) |
Line 4010... | Line 4452... | ||
4010 | return 0; |
4452 | return 0; |
4011 | 4453 | ||
Line 4012... | Line 4454... | ||
4012 | if (connector->edid_blob_ptr) |
4454 | if (edid) |
4013 | drm_property_destroy_blob(dev, connector->edid_blob_ptr); |
- | |
4014 | 4455 | size = EDID_LENGTH * (1 + edid->extensions); |
|
- | 4456 | ||
- | 4457 | ret = drm_property_replace_global_blob(dev, |
|
- | 4458 | &connector->edid_blob_ptr, |
|
4015 | /* Delete edid, when there is none. */ |
4459 | size, |
4016 | if (!edid) { |
4460 | edid, |
4017 | connector->edid_blob_ptr = NULL; |
4461 | &connector->base, |
- | 4462 | dev->mode_config.edid_property); |
|
Line 4018... | Line 4463... | ||
4018 | ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0); |
4463 | return ret; |
- | 4464 | } |
|
- | 4465 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
|
- | 4466 | ||
- | 4467 | /* Some properties could refer to dynamic refcnt'd objects, or things that |
|
4019 | return ret; |
4468 | * need special locking to handle lifetime issues (ie. to ensure the prop |
4020 | } |
4469 | * value doesn't become invalid part way through the property update due to |
- | 4470 | * race). The value returned by reference via 'obj' should be passed back |
|
- | 4471 | * to drm_property_change_valid_put() after the property is set (and the |
|
- | 4472 | * object to which the property is attached has a chance to take it's own |
|
- | 4473 | * reference). |
|
- | 4474 | */ |
|
- | 4475 | bool drm_property_change_valid_get(struct drm_property *property, |
|
4021 | 4476 | uint64_t value, struct drm_mode_object **ref) |
|
4022 | size = EDID_LENGTH * (1 + edid->extensions); |
4477 | { |
Line 4023... | Line -... | ||
4023 | connector->edid_blob_ptr = drm_property_create_blob(connector->dev, |
- | |
4024 | size, edid); |
4478 | int i; |
4025 | if (!connector->edid_blob_ptr) |
- | |
Line -... | Line 4479... | ||
- | 4479 | ||
- | 4480 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) |
|
- | 4481 | return false; |
|
4026 | return -EINVAL; |
4482 | |
- | 4483 | *ref = NULL; |
|
- | 4484 | ||
- | 4485 | if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { |
|
- | 4486 | if (value < property->values[0] || value > property->values[1]) |
|
- | 4487 | return false; |
|
- | 4488 | return true; |
|
- | 4489 | } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) { |
|
- | 4490 | int64_t svalue = U642I64(value); |
|
- | 4491 | ||
- | 4492 | if (svalue < U642I64(property->values[0]) || |
|
- | 4493 | svalue > U642I64(property->values[1])) |
|
- | 4494 | return false; |
|
- | 4495 | return true; |
|
- | 4496 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
|
- | 4497 | uint64_t valid_mask = 0; |
|
- | 4498 | ||
- | 4499 | for (i = 0; i < property->num_values; i++) |
|
- | 4500 | valid_mask |= (1ULL << property->values[i]); |
|
- | 4501 | return !(value & ~valid_mask); |
|
- | 4502 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
|
- | 4503 | struct drm_property_blob *blob; |
|
- | 4504 | ||
- | 4505 | if (value == 0) |
|
- | 4506 | return true; |
|
- | 4507 | ||
- | 4508 | blob = drm_property_lookup_blob(property->dev, value); |
|
- | 4509 | if (blob) { |
|
- | 4510 | *ref = &blob->base; |
|
- | 4511 | return true; |
|
- | 4512 | } else { |
|
- | 4513 | return false; |
|
- | 4514 | } |
|
- | 4515 | } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { |
|
- | 4516 | /* a zero value for an object property translates to null: */ |
|
- | 4517 | if (value == 0) |
|
- | 4518 | return true; |
|
- | 4519 | ||
- | 4520 | /* handle refcnt'd objects specially: */ |
|
- | 4521 | if (property->values[0] == DRM_MODE_OBJECT_FB) { |
|
- | 4522 | struct drm_framebuffer *fb; |
|
- | 4523 | fb = drm_framebuffer_lookup(property->dev, value); |
|
- | 4524 | if (fb) { |
|
- | 4525 | *ref = &fb->base; |
|
- | 4526 | return true; |
|
- | 4527 | } else { |
|
- | 4528 | return false; |
|
- | 4529 | } |
|
- | 4530 | } else { |
|
- | 4531 | return _object_find(property->dev, value, property->values[0]) != NULL; |
|
- | 4532 | } |
|
- | 4533 | } |
|
- | 4534 | ||
- | 4535 | for (i = 0; i < property->num_values; i++) |
|
- | 4536 | if (property->values[i] == value) |
|
- | 4537 | return true; |
|
- | 4538 | return false; |
|
- | 4539 | } |
|
- | 4540 | ||
- | 4541 | void drm_property_change_valid_put(struct drm_property *property, |
|
- | 4542 | struct drm_mode_object *ref) |
|
- | 4543 | { |
|
- | 4544 | if (!ref) |
|
- | 4545 | return; |
|
4027 | 4546 | ||
4028 | ret = drm_object_property_set_value(&connector->base, |
- | |
Line 4029... | Line 4547... | ||
4029 | dev->mode_config.edid_property, |
4547 | if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { |
4030 | connector->edid_blob_ptr->base.id); |
4548 | if (property->values[0] == DRM_MODE_OBJECT_FB) |
Line 4042... | Line 4560... | ||
4042 | int ret = -EINVAL; |
4560 | int ret = -EINVAL; |
4043 | struct drm_connector *connector = obj_to_connector(obj); |
4561 | struct drm_connector *connector = obj_to_connector(obj); |
Line 4044... | Line 4562... | ||
4044 | 4562 | ||
4045 | /* Do DPMS ourselves */ |
4563 | /* Do DPMS ourselves */ |
4046 | if (property == connector->dev->mode_config.dpms_property) { |
- | |
4047 | if (connector->funcs->dpms) |
- | |
4048 | (*connector->funcs->dpms)(connector, (int)value); |
4564 | if (property == connector->dev->mode_config.dpms_property) { |
- | 4565 | ret = 0; |
|
- | 4566 | if (connector->funcs->dpms) |
|
4049 | ret = 0; |
4567 | ret = (*connector->funcs->dpms)(connector, (int)value); |
4050 | } else if (connector->funcs->set_property) |
4568 | } else if (connector->funcs->set_property) |
Line 4051... | Line 4569... | ||
4051 | ret = connector->funcs->set_property(connector, property, value); |
4569 | ret = connector->funcs->set_property(connector, property, value); |
4052 | 4570 | ||
Line 4120... | Line 4638... | ||
4120 | struct drm_file *file_priv) |
4638 | struct drm_file *file_priv) |
4121 | { |
4639 | { |
4122 | struct drm_mode_obj_get_properties *arg = data; |
4640 | struct drm_mode_obj_get_properties *arg = data; |
4123 | struct drm_mode_object *obj; |
4641 | struct drm_mode_object *obj; |
4124 | int ret = 0; |
4642 | int ret = 0; |
4125 | int i; |
- | |
4126 | int copied = 0; |
- | |
4127 | int props_count = 0; |
- | |
4128 | uint32_t __user *props_ptr; |
- | |
4129 | uint64_t __user *prop_values_ptr; |
- | |
Line 4130... | Line 4643... | ||
4130 | 4643 | ||
4131 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4644 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 4132... | Line 4645... | ||
4132 | return -EINVAL; |
4645 | return -EINVAL; |
Line 4141... | Line 4654... | ||
4141 | if (!obj->properties) { |
4654 | if (!obj->properties) { |
4142 | ret = -EINVAL; |
4655 | ret = -EINVAL; |
4143 | goto out; |
4656 | goto out; |
4144 | } |
4657 | } |
Line 4145... | Line 4658... | ||
4145 | 4658 | ||
- | 4659 | ret = get_properties(obj, file_priv->atomic, |
|
- | 4660 | (uint32_t __user *)(unsigned long)(arg->props_ptr), |
|
- | 4661 | (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), |
|
Line 4146... | Line -... | ||
4146 | props_count = obj->properties->count; |
- | |
4147 | - | ||
4148 | /* This ioctl is called twice, once to determine how much space is |
- | |
4149 | * needed, and the 2nd time to fill it. */ |
- | |
4150 | if ((arg->count_props >= props_count) && props_count) { |
- | |
4151 | copied = 0; |
- | |
4152 | props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); |
- | |
4153 | prop_values_ptr = (uint64_t __user *)(unsigned long) |
- | |
4154 | (arg->prop_values_ptr); |
- | |
4155 | for (i = 0; i < props_count; i++) { |
- | |
4156 | if (put_user(obj->properties->ids[i], |
- | |
4157 | props_ptr + copied)) { |
- | |
4158 | ret = -EFAULT; |
- | |
4159 | goto out; |
- | |
4160 | } |
- | |
4161 | if (put_user(obj->properties->values[i], |
- | |
4162 | prop_values_ptr + copied)) { |
- | |
4163 | ret = -EFAULT; |
- | |
4164 | goto out; |
- | |
4165 | } |
- | |
4166 | copied++; |
- | |
4167 | } |
- | |
4168 | } |
4662 | &arg->count_props); |
4169 | arg->count_props = props_count; |
4663 | |
4170 | out: |
4664 | out: |
4171 | drm_modeset_unlock_all(dev); |
4665 | drm_modeset_unlock_all(dev); |
Line 4193... | Line 4687... | ||
4193 | { |
4687 | { |
4194 | struct drm_mode_obj_set_property *arg = data; |
4688 | struct drm_mode_obj_set_property *arg = data; |
4195 | struct drm_mode_object *arg_obj; |
4689 | struct drm_mode_object *arg_obj; |
4196 | struct drm_mode_object *prop_obj; |
4690 | struct drm_mode_object *prop_obj; |
4197 | struct drm_property *property; |
4691 | struct drm_property *property; |
4198 | int ret = -EINVAL; |
4692 | int i, ret = -EINVAL; |
4199 | int i; |
4693 | struct drm_mode_object *ref; |
Line 4200... | Line 4694... | ||
4200 | 4694 | ||
4201 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4695 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 4202... | Line 4696... | ||
4202 | return -EINVAL; |
4696 | return -EINVAL; |
Line 4210... | Line 4704... | ||
4210 | } |
4704 | } |
4211 | if (!arg_obj->properties) |
4705 | if (!arg_obj->properties) |
4212 | goto out; |
4706 | goto out; |
Line 4213... | Line 4707... | ||
4213 | 4707 | ||
4214 | for (i = 0; i < arg_obj->properties->count; i++) |
4708 | for (i = 0; i < arg_obj->properties->count; i++) |
4215 | if (arg_obj->properties->ids[i] == arg->prop_id) |
4709 | if (arg_obj->properties->properties[i]->base.id == arg->prop_id) |
Line 4216... | Line 4710... | ||
4216 | break; |
4710 | break; |
4217 | 4711 | ||
Line 4224... | Line 4718... | ||
4224 | ret = -ENOENT; |
4718 | ret = -ENOENT; |
4225 | goto out; |
4719 | goto out; |
4226 | } |
4720 | } |
4227 | property = obj_to_property(prop_obj); |
4721 | property = obj_to_property(prop_obj); |
Line 4228... | Line 4722... | ||
4228 | 4722 | ||
4229 | if (!drm_property_change_is_valid(property, arg->value)) |
4723 | if (!drm_property_change_valid_get(property, arg->value, &ref)) |
Line 4230... | Line 4724... | ||
4230 | goto out; |
4724 | goto out; |
4231 | 4725 | ||
4232 | switch (arg_obj->type) { |
4726 | switch (arg_obj->type) { |
Line 4241... | Line 4735... | ||
4241 | ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj), |
4735 | ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj), |
4242 | property, arg->value); |
4736 | property, arg->value); |
4243 | break; |
4737 | break; |
4244 | } |
4738 | } |
Line -... | Line 4739... | ||
- | 4739 | ||
- | 4740 | drm_property_change_valid_put(property, ref); |
|
4245 | 4741 | ||
4246 | out: |
4742 | out: |
4247 | drm_modeset_unlock_all(dev); |
4743 | drm_modeset_unlock_all(dev); |
4248 | return ret; |
4744 | return ret; |
4249 | } |
4745 | } |
Line 4291... | Line 4787... | ||
4291 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
4787 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
4292 | int gamma_size) |
4788 | int gamma_size) |
4293 | { |
4789 | { |
4294 | crtc->gamma_size = gamma_size; |
4790 | crtc->gamma_size = gamma_size; |
Line 4295... | Line 4791... | ||
4295 | 4791 | ||
- | 4792 | crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, |
|
4296 | crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); |
4793 | GFP_KERNEL); |
4297 | if (!crtc->gamma_store) { |
4794 | if (!crtc->gamma_store) { |
4298 | crtc->gamma_size = 0; |
4795 | crtc->gamma_size = 0; |
4299 | return -ENOMEM; |
4796 | return -ENOMEM; |
Line 4454... | Line 4951... | ||
4454 | struct drm_crtc *crtc; |
4951 | struct drm_crtc *crtc; |
4455 | struct drm_plane *plane; |
4952 | struct drm_plane *plane; |
4456 | struct drm_encoder *encoder; |
4953 | struct drm_encoder *encoder; |
4457 | struct drm_connector *connector; |
4954 | struct drm_connector *connector; |
Line 4458... | Line 4955... | ||
4458 | 4955 | ||
4459 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) |
4956 | drm_for_each_plane(plane, dev) |
4460 | if (plane->funcs->reset) |
4957 | if (plane->funcs->reset) |
Line 4461... | Line 4958... | ||
4461 | plane->funcs->reset(plane); |
4958 | plane->funcs->reset(plane); |
4462 | 4959 | ||
4463 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
4960 | drm_for_each_crtc(crtc, dev) |
Line 4464... | Line 4961... | ||
4464 | if (crtc->funcs->reset) |
4961 | if (crtc->funcs->reset) |
4465 | crtc->funcs->reset(crtc); |
4962 | crtc->funcs->reset(crtc); |
4466 | 4963 | ||
Line 4467... | Line 4964... | ||
4467 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
4964 | drm_for_each_encoder(encoder, dev) |
4468 | if (encoder->funcs->reset) |
4965 | if (encoder->funcs->reset) |
4469 | encoder->funcs->reset(encoder); |
- | |
4470 | 4966 | encoder->funcs->reset(encoder); |
|
4471 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
4967 | |
4472 | connector->status = connector_status_unknown; |
- | |
- | 4968 | mutex_lock(&dev->mode_config.mutex); |
|
4473 | 4969 | drm_for_each_connector(connector, dev) |
|
4474 | if (connector->funcs->reset) |
4970 | if (connector->funcs->reset) |
4475 | connector->funcs->reset(connector); |
4971 | connector->funcs->reset(connector); |
4476 | } |
4972 | mutex_unlock(&dev->mode_config.mutex); |
4477 | } |
4973 | } |
Line 4708... | Line 5204... | ||
4708 | unsigned int drm_rotation_simplify(unsigned int rotation, |
5204 | unsigned int drm_rotation_simplify(unsigned int rotation, |
4709 | unsigned int supported_rotations) |
5205 | unsigned int supported_rotations) |
4710 | { |
5206 | { |
4711 | if (rotation & ~supported_rotations) { |
5207 | if (rotation & ~supported_rotations) { |
4712 | rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y); |
5208 | rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y); |
- | 5209 | rotation = (rotation & DRM_REFLECT_MASK) | |
|
4713 | rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4); |
5210 | BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4); |
4714 | } |
5211 | } |
Line 4715... | Line 5212... | ||
4715 | 5212 | ||
4716 | return rotation; |
5213 | return rotation; |
4717 | } |
5214 | } |
Line 4733... | Line 5230... | ||
4733 | { |
5230 | { |
4734 | mutex_init(&dev->mode_config.mutex); |
5231 | mutex_init(&dev->mode_config.mutex); |
4735 | drm_modeset_lock_init(&dev->mode_config.connection_mutex); |
5232 | drm_modeset_lock_init(&dev->mode_config.connection_mutex); |
4736 | mutex_init(&dev->mode_config.idr_mutex); |
5233 | mutex_init(&dev->mode_config.idr_mutex); |
4737 | mutex_init(&dev->mode_config.fb_lock); |
5234 | mutex_init(&dev->mode_config.fb_lock); |
- | 5235 | mutex_init(&dev->mode_config.blob_lock); |
|
4738 | INIT_LIST_HEAD(&dev->mode_config.fb_list); |
5236 | INIT_LIST_HEAD(&dev->mode_config.fb_list); |
4739 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
5237 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
4740 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
5238 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
4741 | INIT_LIST_HEAD(&dev->mode_config.bridge_list); |
- | |
4742 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
5239 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
4743 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
5240 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
4744 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
5241 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
4745 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
5242 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
4746 | idr_init(&dev->mode_config.crtc_idr); |
5243 | idr_init(&dev->mode_config.crtc_idr); |
4747 | idr_init(&dev->mode_config.tile_idr); |
5244 | idr_init(&dev->mode_config.tile_idr); |
Line 4748... | Line 5245... | ||
4748 | 5245 | ||
4749 | drm_modeset_lock_all(dev); |
- | |
4750 | drm_mode_create_standard_connector_properties(dev); |
5246 | drm_modeset_lock_all(dev); |
4751 | drm_mode_create_standard_plane_properties(dev); |
5247 | drm_mode_create_standard_properties(dev); |
Line 4752... | Line 5248... | ||
4752 | drm_modeset_unlock_all(dev); |
5248 | drm_modeset_unlock_all(dev); |
4753 | 5249 | ||
4754 | /* Just to be sure */ |
5250 | /* Just to be sure */ |
Line 4777... | Line 5273... | ||
4777 | void drm_mode_config_cleanup(struct drm_device *dev) |
5273 | void drm_mode_config_cleanup(struct drm_device *dev) |
4778 | { |
5274 | { |
4779 | struct drm_connector *connector, *ot; |
5275 | struct drm_connector *connector, *ot; |
4780 | struct drm_crtc *crtc, *ct; |
5276 | struct drm_crtc *crtc, *ct; |
4781 | struct drm_encoder *encoder, *enct; |
5277 | struct drm_encoder *encoder, *enct; |
4782 | struct drm_bridge *bridge, *brt; |
- | |
4783 | struct drm_framebuffer *fb, *fbt; |
5278 | struct drm_framebuffer *fb, *fbt; |
4784 | struct drm_property *property, *pt; |
5279 | struct drm_property *property, *pt; |
4785 | struct drm_property_blob *blob, *bt; |
5280 | struct drm_property_blob *blob, *bt; |
4786 | struct drm_plane *plane, *plt; |
5281 | struct drm_plane *plane, *plt; |
Line 4787... | Line 5282... | ||
4787 | 5282 | ||
4788 | list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, |
5283 | list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, |
4789 | head) { |
5284 | head) { |
4790 | encoder->funcs->destroy(encoder); |
5285 | encoder->funcs->destroy(encoder); |
Line 4791... | Line -... | ||
4791 | } |
- | |
4792 | - | ||
4793 | list_for_each_entry_safe(bridge, brt, |
- | |
4794 | &dev->mode_config.bridge_list, head) { |
- | |
4795 | bridge->funcs->destroy(bridge); |
- | |
4796 | } |
5286 | } |
4797 | 5287 | ||
4798 | list_for_each_entry_safe(connector, ot, |
5288 | list_for_each_entry_safe(connector, ot, |
4799 | &dev->mode_config.connector_list, head) { |
5289 | &dev->mode_config.connector_list, head) { |
Line 4804... | Line 5294... | ||
4804 | head) { |
5294 | head) { |
4805 | drm_property_destroy(dev, property); |
5295 | drm_property_destroy(dev, property); |
4806 | } |
5296 | } |
Line 4807... | Line 5297... | ||
4807 | 5297 | ||
4808 | list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, |
5298 | list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, |
4809 | head) { |
5299 | head_global) { |
4810 | drm_property_destroy_blob(dev, blob); |
5300 | drm_property_unreference_blob(blob); |
Line 4811... | Line 5301... | ||
4811 | } |
5301 | } |
4812 | 5302 | ||
4813 | /* |
5303 | /* |
Line 4818... | Line 5308... | ||
4818 | * Also, if there are any framebuffers left, that's a driver leak now, |
5308 | * Also, if there are any framebuffers left, that's a driver leak now, |
4819 | * so politely WARN about this. |
5309 | * so politely WARN about this. |
4820 | */ |
5310 | */ |
4821 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); |
5311 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); |
4822 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
5312 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
4823 | drm_framebuffer_remove(fb); |
5313 | drm_framebuffer_free(&fb->refcount); |
4824 | } |
5314 | } |
Line 4825... | Line 5315... | ||
4825 | 5315 | ||
4826 | list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, |
5316 | list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, |
4827 | head) { |
5317 | head) { |
Line 4903... | Line 5393... | ||
4903 | struct drm_tile_group *tg; |
5393 | struct drm_tile_group *tg; |
4904 | int id; |
5394 | int id; |
4905 | mutex_lock(&dev->mode_config.idr_mutex); |
5395 | mutex_lock(&dev->mode_config.idr_mutex); |
4906 | idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { |
5396 | idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { |
4907 | if (!memcmp(tg->group_data, topology, 8)) { |
5397 | if (!memcmp(tg->group_data, topology, 8)) { |
4908 | // if (!kref_get_unless_zero(&tg->refcount)) |
5398 | if (!kref_get_unless_zero(&tg->refcount)) |
4909 | // tg = NULL; |
5399 | tg = NULL; |
4910 | mutex_unlock(&dev->mode_config.idr_mutex); |
5400 | mutex_unlock(&dev->mode_config.idr_mutex); |
4911 | return tg; |
5401 | return tg; |
4912 | } |
5402 | } |
4913 | } |
5403 | } |
4914 | mutex_unlock(&dev->mode_config.idr_mutex); |
5404 | mutex_unlock(&dev->mode_config.idr_mutex); |
4915 | return NULL; |
5405 | return NULL; |
4916 | } |
5406 | } |
- | 5407 | EXPORT_SYMBOL(drm_mode_get_tile_group); |
|
Line 4917... | Line 5408... | ||
4917 | 5408 | ||
4918 | /** |
5409 | /** |
4919 | * drm_mode_create_tile_group - create a tile group from a displayid description |
5410 | * drm_mode_create_tile_group - create a tile group from a displayid description |
4920 | * @dev: DRM device |
5411 | * @dev: DRM device |
Line 4950... | Line 5441... | ||
4950 | } |
5441 | } |
Line 4951... | Line 5442... | ||
4951 | 5442 | ||
4952 | mutex_unlock(&dev->mode_config.idr_mutex); |
5443 | mutex_unlock(&dev->mode_config.idr_mutex); |
4953 | return tg; |
5444 | return tg; |
- | 5445 | } |