Rev 5060 | Rev 5367 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5060 | Rev 5271 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | #include |
38 | #include |
39 | #include |
39 | #include |
40 | #include |
40 | #include |
Line 41... | Line 41... | ||
41 | 41 | ||
- | 42 | #include "drm_crtc_internal.h" |
|
Line 42... | Line 43... | ||
42 | #include "drm_crtc_internal.h" |
43 | #include "drm_internal.h" |
43 | 44 | ||
44 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, |
45 | static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, |
Line 45... | Line -... | ||
45 | struct drm_mode_fb_cmd2 *r, |
- | |
46 | struct drm_file *file_priv); |
- | |
47 | - | ||
48 | /** |
- | |
49 | * drm_modeset_lock_all - take all modeset locks |
- | |
50 | * @dev: drm device |
- | |
51 | * |
- | |
52 | * This function takes all modeset locks, suitable where a more fine-grained |
- | |
53 | * scheme isn't (yet) implemented. Locks must be dropped with |
- | |
54 | * drm_modeset_unlock_all. |
- | |
55 | */ |
- | |
56 | void drm_modeset_lock_all(struct drm_device *dev) |
- | |
57 | { |
- | |
58 | struct drm_mode_config *config = &dev->mode_config; |
- | |
59 | struct drm_modeset_acquire_ctx *ctx; |
- | |
60 | int ret; |
- | |
61 | - | ||
62 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); |
- | |
63 | if (WARN_ON(!ctx)) |
- | |
64 | return; |
- | |
65 | - | ||
66 | mutex_lock(&config->mutex); |
- | |
67 | - | ||
68 | drm_modeset_acquire_init(ctx, 0); |
- | |
69 | - | ||
70 | retry: |
- | |
71 | ret = drm_modeset_lock(&config->connection_mutex, ctx); |
- | |
72 | if (ret) |
- | |
73 | goto fail; |
- | |
74 | ret = drm_modeset_lock_all_crtcs(dev, ctx); |
- | |
75 | if (ret) |
- | |
76 | goto fail; |
- | |
77 | - | ||
78 | WARN_ON(config->acquire_ctx); |
- | |
79 | - | ||
80 | /* now we hold the locks, so now that it is safe, stash the |
- | |
81 | * ctx for drm_modeset_unlock_all(): |
- | |
82 | */ |
- | |
83 | config->acquire_ctx = ctx; |
- | |
84 | - | ||
85 | drm_warn_on_modeset_not_all_locked(dev); |
- | |
86 | - | ||
87 | return; |
- | |
88 | - | ||
89 | fail: |
- | |
90 | if (ret == -EDEADLK) { |
- | |
91 | drm_modeset_backoff(ctx); |
- | |
92 | goto retry; |
- | |
93 | } |
- | |
94 | } |
- | |
95 | EXPORT_SYMBOL(drm_modeset_lock_all); |
- | |
96 | - | ||
97 | /** |
- | |
98 | * drm_modeset_unlock_all - drop all modeset locks |
- | |
99 | * @dev: device |
- | |
100 | * |
- | |
101 | * This function drop all modeset locks taken by drm_modeset_lock_all. |
- | |
102 | */ |
- | |
103 | void drm_modeset_unlock_all(struct drm_device *dev) |
- | |
104 | { |
- | |
105 | struct drm_mode_config *config = &dev->mode_config; |
- | |
106 | struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx; |
- | |
107 | - | ||
108 | if (WARN_ON(!ctx)) |
- | |
109 | return; |
- | |
110 | - | ||
111 | config->acquire_ctx = NULL; |
- | |
112 | drm_modeset_drop_locks(ctx); |
- | |
113 | drm_modeset_acquire_fini(ctx); |
- | |
114 | - | ||
115 | kfree(ctx); |
- | |
116 | - | ||
117 | mutex_unlock(&dev->mode_config.mutex); |
- | |
118 | } |
- | |
119 | EXPORT_SYMBOL(drm_modeset_unlock_all); |
- | |
120 | - | ||
121 | /** |
- | |
122 | * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked |
- | |
123 | * @dev: device |
- | |
124 | * |
- | |
125 | * Useful as a debug assert. |
- | |
126 | */ |
- | |
127 | void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) |
- | |
128 | { |
- | |
129 | struct drm_crtc *crtc; |
- | |
130 | - | ||
131 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
- | |
132 | WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); |
- | |
133 | - | ||
134 | WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
- | |
135 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
- | |
136 | } |
46 | struct drm_mode_fb_cmd2 *r, |
137 | EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); |
47 | struct drm_file *file_priv); |
138 | 48 | ||
139 | /* Avoid boilerplate. I'm tired of typing. */ |
49 | /* Avoid boilerplate. I'm tired of typing. */ |
140 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
50 | #define DRM_ENUM_NAME_FN(fnname, list) \ |
Line 509... | Line 419... | ||
509 | 419 | ||
510 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
420 | ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); |
511 | if (ret) |
421 | if (ret) |
Line 512... | Line -... | ||
512 | goto out; |
- | |
513 | - | ||
514 | /* Grab the idr reference. */ |
- | |
515 | drm_framebuffer_reference(fb); |
422 | goto out; |
516 | 423 | ||
517 | dev->mode_config.num_fb++; |
424 | dev->mode_config.num_fb++; |
518 | list_add(&fb->head, &dev->mode_config.fb_list); |
425 | list_add(&fb->head, &dev->mode_config.fb_list); |
Line 519... | Line 426... | ||
519 | out: |
426 | out: |
520 | mutex_unlock(&dev->mode_config.fb_lock); |
427 | mutex_unlock(&dev->mode_config.fb_lock); |
521 | 428 | ||
Line -... | Line 429... | ||
- | 429 | return 0; |
|
- | 430 | } |
|
- | 431 | EXPORT_SYMBOL(drm_framebuffer_init); |
|
- | 432 | ||
- | 433 | /* dev->mode_config.fb_lock must be held! */ |
|
- | 434 | static void __drm_framebuffer_unregister(struct drm_device *dev, |
|
- | 435 | struct drm_framebuffer *fb) |
|
- | 436 | { |
|
- | 437 | mutex_lock(&dev->mode_config.idr_mutex); |
|
- | 438 | idr_remove(&dev->mode_config.crtc_idr, fb->base.id); |
|
- | 439 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
522 | return 0; |
440 | |
523 | } |
441 | fb->base.id = 0; |
524 | EXPORT_SYMBOL(drm_framebuffer_init); |
442 | } |
525 | 443 | ||
- | 444 | static void drm_framebuffer_free(struct kref *kref) |
|
- | 445 | { |
|
- | 446 | struct drm_framebuffer *fb = |
|
- | 447 | container_of(kref, struct drm_framebuffer, refcount); |
|
- | 448 | struct drm_device *dev = fb->dev; |
|
- | 449 | ||
- | 450 | /* |
|
- | 451 | * The lookup idr holds a weak reference, which has not necessarily been |
|
- | 452 | * removed at this point. Check for that. |
|
- | 453 | */ |
|
- | 454 | mutex_lock(&dev->mode_config.fb_lock); |
|
- | 455 | if (fb->base.id) { |
|
- | 456 | /* Mark fb as reaped and drop idr ref. */ |
|
526 | static void drm_framebuffer_free(struct kref *kref) |
457 | __drm_framebuffer_unregister(dev, fb); |
527 | { |
458 | } |
Line 528... | Line 459... | ||
528 | struct drm_framebuffer *fb = |
459 | mutex_unlock(&dev->mode_config.fb_lock); |
529 | container_of(kref, struct drm_framebuffer, refcount); |
460 | |
Line 606... | Line 537... | ||
606 | { |
537 | { |
607 | DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount)); |
538 | DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount)); |
608 | kref_put(&fb->refcount, drm_framebuffer_free_bug); |
539 | kref_put(&fb->refcount, drm_framebuffer_free_bug); |
609 | } |
540 | } |
Line 610... | Line -... | ||
610 | - | ||
611 | /* dev->mode_config.fb_lock must be held! */ |
- | |
612 | static void __drm_framebuffer_unregister(struct drm_device *dev, |
- | |
613 | struct drm_framebuffer *fb) |
- | |
614 | { |
- | |
615 | mutex_lock(&dev->mode_config.idr_mutex); |
- | |
616 | idr_remove(&dev->mode_config.crtc_idr, fb->base.id); |
- | |
617 | mutex_unlock(&dev->mode_config.idr_mutex); |
- | |
618 | - | ||
619 | fb->base.id = 0; |
- | |
620 | - | ||
621 | __drm_framebuffer_unreference(fb); |
- | |
622 | } |
- | |
623 | 541 | ||
624 | /** |
542 | /** |
625 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr |
543 | * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr |
626 | * @fb: fb to unregister |
544 | * @fb: fb to unregister |
627 | * |
545 | * |
Line 758... | Line 676... | ||
758 | 676 | ||
759 | crtc->dev = dev; |
677 | crtc->dev = dev; |
760 | crtc->funcs = funcs; |
678 | crtc->funcs = funcs; |
Line 761... | Line -... | ||
761 | crtc->invert_dimensions = false; |
- | |
762 | 679 | crtc->invert_dimensions = false; |
|
763 | drm_modeset_lock_all(dev); |
- | |
764 | drm_modeset_lock_init(&crtc->mutex); |
- | |
765 | /* dropped by _unlock_all(): */ |
- | |
766 | drm_modeset_lock(&crtc->mutex, config->acquire_ctx); |
680 | |
767 | 681 | drm_modeset_lock_init(&crtc->mutex); |
|
768 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
682 | ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); |
Line 769... | Line 683... | ||
769 | if (ret) |
683 | if (ret) |
Line 770... | Line 684... | ||
770 | goto out; |
684 | return ret; |
771 | 685 | ||
Line 779... | Line 693... | ||
779 | if (primary) |
693 | if (primary) |
780 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); |
694 | primary->possible_crtcs = 1 << drm_crtc_index(crtc); |
781 | if (cursor) |
695 | if (cursor) |
782 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
696 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
Line 783... | Line -... | ||
783 | - | ||
784 | out: |
- | |
785 | drm_modeset_unlock_all(dev); |
- | |
786 | 697 | ||
787 | return ret; |
698 | return 0; |
788 | } |
699 | } |
Line 789... | Line 700... | ||
789 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
700 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
790 | 701 | ||
Line 806... | Line 717... | ||
806 | drm_modeset_lock_fini(&crtc->mutex); |
717 | drm_modeset_lock_fini(&crtc->mutex); |
Line 807... | Line 718... | ||
807 | 718 | ||
808 | drm_mode_object_put(dev, &crtc->base); |
719 | drm_mode_object_put(dev, &crtc->base); |
809 | list_del(&crtc->head); |
720 | list_del(&crtc->head); |
- | 721 | dev->mode_config.num_crtc--; |
|
- | 722 | ||
- | 723 | WARN_ON(crtc->state && !crtc->funcs->atomic_destroy_state); |
|
- | 724 | if (crtc->state && crtc->funcs->atomic_destroy_state) |
|
- | 725 | crtc->funcs->atomic_destroy_state(crtc, crtc->state); |
|
- | 726 | ||
810 | dev->mode_config.num_crtc--; |
727 | memset(crtc, 0, sizeof(*crtc)); |
811 | } |
728 | } |
Line 812... | Line 729... | ||
812 | EXPORT_SYMBOL(drm_crtc_cleanup); |
729 | EXPORT_SYMBOL(drm_crtc_cleanup); |
813 | 730 | ||
Line 947... | Line 864... | ||
947 | drm_mode_object_put(dev, &connector->base); |
864 | drm_mode_object_put(dev, &connector->base); |
948 | kfree(connector->name); |
865 | kfree(connector->name); |
949 | connector->name = NULL; |
866 | connector->name = NULL; |
950 | list_del(&connector->head); |
867 | list_del(&connector->head); |
951 | dev->mode_config.num_connector--; |
868 | dev->mode_config.num_connector--; |
- | 869 | ||
- | 870 | WARN_ON(connector->state && !connector->funcs->atomic_destroy_state); |
|
- | 871 | if (connector->state && connector->funcs->atomic_destroy_state) |
|
- | 872 | connector->funcs->atomic_destroy_state(connector, |
|
- | 873 | connector->state); |
|
- | 874 | ||
- | 875 | memset(connector, 0, sizeof(*connector)); |
|
952 | } |
876 | } |
953 | EXPORT_SYMBOL(drm_connector_cleanup); |
877 | EXPORT_SYMBOL(drm_connector_cleanup); |
Line 954... | Line 878... | ||
954 | 878 | ||
- | 879 | /** |
|
- | 880 | * drm_connector_index - find the index of a registered connector |
|
- | 881 | * @connector: connector to find index for |
|
- | 882 | * |
|
- | 883 | * Given a registered connector, return the index of that connector within a DRM |
|
- | 884 | * device's list of connectors. |
|
- | 885 | */ |
|
- | 886 | unsigned int drm_connector_index(struct drm_connector *connector) |
|
- | 887 | { |
|
- | 888 | unsigned int index = 0; |
|
- | 889 | struct drm_connector *tmp; |
|
- | 890 | struct drm_mode_config *config = &connector->dev->mode_config; |
|
- | 891 | ||
- | 892 | WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); |
|
- | 893 | ||
- | 894 | list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) { |
|
- | 895 | if (tmp == connector) |
|
- | 896 | return index; |
|
- | 897 | ||
- | 898 | index++; |
|
- | 899 | } |
|
- | 900 | ||
- | 901 | BUG(); |
|
- | 902 | } |
|
- | 903 | EXPORT_SYMBOL(drm_connector_index); |
|
- | 904 | ||
955 | /** |
905 | /** |
956 | * drm_connector_register - register a connector |
906 | * drm_connector_register - register a connector |
957 | * @connector: the connector to register |
907 | * @connector: the connector to register |
958 | * |
908 | * |
959 | * Register userspace interfaces for a connector |
909 | * Register userspace interfaces for a connector |
Line 1050... | Line 1000... | ||
1050 | drm_modeset_lock_all(dev); |
1000 | drm_modeset_lock_all(dev); |
1051 | drm_mode_object_put(dev, &bridge->base); |
1001 | drm_mode_object_put(dev, &bridge->base); |
1052 | list_del(&bridge->head); |
1002 | list_del(&bridge->head); |
1053 | dev->mode_config.num_bridge--; |
1003 | dev->mode_config.num_bridge--; |
1054 | drm_modeset_unlock_all(dev); |
1004 | drm_modeset_unlock_all(dev); |
- | 1005 | ||
- | 1006 | memset(bridge, 0, sizeof(*bridge)); |
|
1055 | } |
1007 | } |
1056 | EXPORT_SYMBOL(drm_bridge_cleanup); |
1008 | EXPORT_SYMBOL(drm_bridge_cleanup); |
Line 1057... | Line 1009... | ||
1057 | 1009 | ||
1058 | /** |
1010 | /** |
Line 1116... | Line 1068... | ||
1116 | { |
1068 | { |
1117 | struct drm_device *dev = encoder->dev; |
1069 | struct drm_device *dev = encoder->dev; |
1118 | drm_modeset_lock_all(dev); |
1070 | drm_modeset_lock_all(dev); |
1119 | drm_mode_object_put(dev, &encoder->base); |
1071 | drm_mode_object_put(dev, &encoder->base); |
1120 | kfree(encoder->name); |
1072 | kfree(encoder->name); |
1121 | encoder->name = NULL; |
- | |
1122 | list_del(&encoder->head); |
1073 | list_del(&encoder->head); |
1123 | dev->mode_config.num_encoder--; |
1074 | dev->mode_config.num_encoder--; |
1124 | drm_modeset_unlock_all(dev); |
1075 | drm_modeset_unlock_all(dev); |
- | 1076 | ||
- | 1077 | memset(encoder, 0, sizeof(*encoder)); |
|
1125 | } |
1078 | } |
1126 | EXPORT_SYMBOL(drm_encoder_cleanup); |
1079 | EXPORT_SYMBOL(drm_encoder_cleanup); |
Line 1127... | Line 1080... | ||
1127 | 1080 | ||
1128 | /** |
1081 | /** |
Line 1146... | Line 1099... | ||
1146 | const uint32_t *formats, uint32_t format_count, |
1099 | const uint32_t *formats, uint32_t format_count, |
1147 | enum drm_plane_type type) |
1100 | enum drm_plane_type type) |
1148 | { |
1101 | { |
1149 | int ret; |
1102 | int ret; |
Line 1150... | Line -... | ||
1150 | - | ||
1151 | drm_modeset_lock_all(dev); |
- | |
1152 | 1103 | ||
1153 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
1104 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
1154 | if (ret) |
1105 | if (ret) |
- | 1106 | return ret; |
|
- | 1107 | ||
Line 1155... | Line 1108... | ||
1155 | goto out; |
1108 | drm_modeset_lock_init(&plane->mutex); |
1156 | 1109 | ||
1157 | plane->base.properties = &plane->properties; |
1110 | plane->base.properties = &plane->properties; |
1158 | plane->dev = dev; |
1111 | plane->dev = dev; |
1159 | plane->funcs = funcs; |
1112 | plane->funcs = funcs; |
1160 | plane->format_types = kmalloc(sizeof(uint32_t) * format_count, |
1113 | plane->format_types = kmalloc(sizeof(uint32_t) * format_count, |
1161 | GFP_KERNEL); |
1114 | GFP_KERNEL); |
1162 | if (!plane->format_types) { |
1115 | if (!plane->format_types) { |
1163 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1116 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1164 | drm_mode_object_put(dev, &plane->base); |
- | |
1165 | ret = -ENOMEM; |
1117 | drm_mode_object_put(dev, &plane->base); |
Line 1166... | Line 1118... | ||
1166 | goto out; |
1118 | return -ENOMEM; |
1167 | } |
1119 | } |
1168 | 1120 | ||
Line 1178... | Line 1130... | ||
1178 | 1130 | ||
1179 | drm_object_attach_property(&plane->base, |
1131 | drm_object_attach_property(&plane->base, |
1180 | dev->mode_config.plane_type_property, |
1132 | dev->mode_config.plane_type_property, |
Line 1181... | Line -... | ||
1181 | plane->type); |
- | |
1182 | - | ||
1183 | out: |
- | |
1184 | drm_modeset_unlock_all(dev); |
1133 | plane->type); |
1185 | 1134 | ||
1186 | return ret; |
1135 | return 0; |
Line 1187... | Line 1136... | ||
1187 | } |
1136 | } |
1188 | EXPORT_SYMBOL(drm_universal_plane_init); |
1137 | EXPORT_SYMBOL(drm_universal_plane_init); |
Line 1239... | Line 1188... | ||
1239 | list_del(&plane->head); |
1188 | list_del(&plane->head); |
1240 | dev->mode_config.num_total_plane--; |
1189 | dev->mode_config.num_total_plane--; |
1241 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1190 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1242 | dev->mode_config.num_overlay_plane--; |
1191 | dev->mode_config.num_overlay_plane--; |
1243 | drm_modeset_unlock_all(dev); |
1192 | drm_modeset_unlock_all(dev); |
- | 1193 | ||
- | 1194 | WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); |
|
- | 1195 | if (plane->state && plane->funcs->atomic_destroy_state) |
|
- | 1196 | plane->funcs->atomic_destroy_state(plane, plane->state); |
|
- | 1197 | ||
- | 1198 | memset(plane, 0, sizeof(*plane)); |
|
1244 | } |
1199 | } |
1245 | EXPORT_SYMBOL(drm_plane_cleanup); |
1200 | EXPORT_SYMBOL(drm_plane_cleanup); |
Line 1246... | Line 1201... | ||
1246 | 1201 | ||
- | 1202 | /** |
|
- | 1203 | * drm_plane_index - find the index of a registered plane |
|
- | 1204 | * @plane: plane to find index for |
|
- | 1205 | * |
|
- | 1206 | * Given a registered plane, return the index of that CRTC within a DRM |
|
- | 1207 | * device's list of planes. |
|
- | 1208 | */ |
|
- | 1209 | unsigned int drm_plane_index(struct drm_plane *plane) |
|
- | 1210 | { |
|
- | 1211 | unsigned int index = 0; |
|
- | 1212 | struct drm_plane *tmp; |
|
- | 1213 | ||
- | 1214 | list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) { |
|
- | 1215 | if (tmp == plane) |
|
- | 1216 | return index; |
|
- | 1217 | ||
- | 1218 | index++; |
|
- | 1219 | } |
|
- | 1220 | ||
- | 1221 | BUG(); |
|
- | 1222 | } |
|
- | 1223 | EXPORT_SYMBOL(drm_plane_index); |
|
- | 1224 | ||
1247 | /** |
1225 | /** |
1248 | * drm_plane_force_disable - Forcibly disable a plane |
1226 | * drm_plane_force_disable - Forcibly disable a plane |
1249 | * @plane: plane to disable |
1227 | * @plane: plane to disable |
1250 | * |
1228 | * |
1251 | * Forces the plane to be disabled. |
1229 | * Forces the plane to be disabled. |
1252 | * |
1230 | * |
1253 | * Used when the plane's current framebuffer is destroyed, |
1231 | * Used when the plane's current framebuffer is destroyed, |
1254 | * and when restoring fbdev mode. |
1232 | * and when restoring fbdev mode. |
1255 | */ |
1233 | */ |
1256 | void drm_plane_force_disable(struct drm_plane *plane) |
1234 | void drm_plane_force_disable(struct drm_plane *plane) |
1257 | { |
- | |
1258 | struct drm_framebuffer *old_fb = plane->fb; |
1235 | { |
Line 1259... | Line 1236... | ||
1259 | int ret; |
1236 | int ret; |
1260 | 1237 | ||
Line -... | Line 1238... | ||
- | 1238 | if (!plane->fb) |
|
1261 | if (!old_fb) |
1239 | return; |
1262 | return; |
1240 | |
1263 | 1241 | plane->old_fb = plane->fb; |
|
- | 1242 | ret = plane->funcs->disable_plane(plane); |
|
1264 | ret = plane->funcs->disable_plane(plane); |
1243 | if (ret) { |
1265 | if (ret) { |
1244 | DRM_ERROR("failed to disable plane with busy fb\n"); |
1266 | DRM_ERROR("failed to disable plane with busy fb\n"); |
1245 | plane->old_fb = NULL; |
1267 | return; |
1246 | return; |
- | 1247 | } |
|
1268 | } |
1248 | /* disconnect the plane from the fb and crtc: */ |
1269 | /* disconnect the plane from the fb and crtc: */ |
1249 | __drm_framebuffer_unreference(plane->old_fb); |
1270 | __drm_framebuffer_unreference(old_fb); |
1250 | plane->old_fb = NULL; |
1271 | plane->fb = NULL; |
1251 | plane->fb = NULL; |
Line 1296... | Line 1276... | ||
1296 | DRM_MODE_PROP_BLOB | |
1276 | DRM_MODE_PROP_BLOB | |
1297 | DRM_MODE_PROP_IMMUTABLE, |
1277 | DRM_MODE_PROP_IMMUTABLE, |
1298 | "PATH", 0); |
1278 | "PATH", 0); |
1299 | dev->mode_config.path_property = dev_path; |
1279 | dev->mode_config.path_property = dev_path; |
Line -... | Line 1280... | ||
- | 1280 | ||
- | 1281 | dev->mode_config.tile_property = drm_property_create(dev, |
|
- | 1282 | DRM_MODE_PROP_BLOB | |
|
- | 1283 | DRM_MODE_PROP_IMMUTABLE, |
|
- | 1284 | "TILE", 0); |
|
1300 | 1285 | ||
1301 | return 0; |
1286 | return 0; |
Line 1302... | Line 1287... | ||
1302 | } |
1287 | } |
1303 | 1288 | ||
Line 1356... | Line 1341... | ||
1356 | * Called by a driver's TV initialization routine, this function creates |
1341 | * Called by a driver's TV initialization routine, this function creates |
1357 | * the TV specific connector properties for a given device. Caller is |
1342 | * the TV specific connector properties for a given device. Caller is |
1358 | * responsible for allocating a list of format names and passing them to |
1343 | * responsible for allocating a list of format names and passing them to |
1359 | * this routine. |
1344 | * this routine. |
1360 | */ |
1345 | */ |
1361 | int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, |
1346 | int drm_mode_create_tv_properties(struct drm_device *dev, |
- | 1347 | unsigned int num_modes, |
|
1362 | char *modes[]) |
1348 | char *modes[]) |
1363 | { |
1349 | { |
1364 | struct drm_property *tv_selector; |
1350 | struct drm_property *tv_selector; |
1365 | struct drm_property *tv_subconnector; |
1351 | struct drm_property *tv_subconnector; |
1366 | int i; |
1352 | unsigned int i; |
Line 1367... | Line 1353... | ||
1367 | 1353 | ||
1368 | if (dev->mode_config.tv_select_subconnector_property) |
1354 | if (dev->mode_config.tv_select_subconnector_property) |
Line 1369... | Line 1355... | ||
1369 | return 0; |
1355 | return 0; |
Line 1459... | Line 1445... | ||
1459 | * |
1445 | * |
1460 | * Called by a driver the first time it's needed, must be attached to desired |
1446 | * Called by a driver the first time it's needed, must be attached to desired |
1461 | * connectors. |
1447 | * connectors. |
1462 | * |
1448 | * |
1463 | * Returns: |
1449 | * Returns: |
1464 | * Zero on success, errno on failure. |
1450 | * Zero on success, negative errno on failure. |
1465 | */ |
1451 | */ |
1466 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) |
1452 | int drm_mode_create_aspect_ratio_property(struct drm_device *dev) |
1467 | { |
1453 | { |
1468 | if (dev->mode_config.aspect_ratio_property) |
1454 | if (dev->mode_config.aspect_ratio_property) |
1469 | return 0; |
1455 | return 0; |
Line 1503... | Line 1489... | ||
1503 | 1489 | ||
1504 | return 0; |
1490 | return 0; |
1505 | } |
1491 | } |
Line -... | Line 1492... | ||
- | 1492 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); |
|
- | 1493 | ||
- | 1494 | /** |
|
- | 1495 | * drm_mode_create_suggested_offset_properties - create suggests offset properties |
|
- | 1496 | * @dev: DRM device |
|
- | 1497 | * |
|
- | 1498 | * Create the the suggested x/y offset property for connectors. |
|
- | 1499 | */ |
|
- | 1500 | int drm_mode_create_suggested_offset_properties(struct drm_device *dev) |
|
- | 1501 | { |
|
- | 1502 | if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property) |
|
- | 1503 | return 0; |
|
- | 1504 | ||
- | 1505 | dev->mode_config.suggested_x_property = |
|
- | 1506 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff); |
|
- | 1507 | ||
- | 1508 | dev->mode_config.suggested_y_property = |
|
- | 1509 | drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff); |
|
- | 1510 | ||
- | 1511 | if (dev->mode_config.suggested_x_property == NULL || |
|
- | 1512 | dev->mode_config.suggested_y_property == NULL) |
|
- | 1513 | return -ENOMEM; |
|
- | 1514 | return 0; |
|
- | 1515 | } |
|
1506 | EXPORT_SYMBOL(drm_mode_create_dirty_info_property); |
1516 | EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties); |
1507 | 1517 | ||
1508 | static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) |
1518 | static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) |
Line 1509... | Line 1519... | ||
1509 | { |
1519 | { |
Line 1619... | Line 1629... | ||
1619 | * |
1629 | * |
1620 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
1630 | * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to |
1621 | * the caller. |
1631 | * the caller. |
1622 | * |
1632 | * |
1623 | * Returns: |
1633 | * Returns: |
1624 | * Zero on success, errno on failure. |
1634 | * Zero on success, negative errno on failure. |
1625 | */ |
1635 | */ |
1626 | static int drm_crtc_convert_umode(struct drm_display_mode *out, |
1636 | static int drm_crtc_convert_umode(struct drm_display_mode *out, |
1627 | const struct drm_mode_modeinfo *in) |
1637 | const struct drm_mode_modeinfo *in) |
1628 | { |
1638 | { |
1629 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
1639 | if (in->clock > INT_MAX || in->vrefresh > INT_MAX) |
Line 1664... | Line 1674... | ||
1664 | * them to the user, including CRTC, connector and framebuffer configuration. |
1674 | * them to the user, including CRTC, connector and framebuffer configuration. |
1665 | * |
1675 | * |
1666 | * Called by the user via ioctl. |
1676 | * Called by the user via ioctl. |
1667 | * |
1677 | * |
1668 | * Returns: |
1678 | * Returns: |
1669 | * Zero on success, errno on failure. |
1679 | * Zero on success, negative errno on failure. |
1670 | */ |
1680 | */ |
1671 | int drm_mode_getresources(struct drm_device *dev, void *data, |
1681 | int drm_mode_getresources(struct drm_device *dev, void *data, |
1672 | struct drm_file *file_priv) |
1682 | struct drm_file *file_priv) |
1673 | { |
1683 | { |
1674 | struct drm_mode_card_res *card_res = data; |
1684 | struct drm_mode_card_res *card_res = data; |
Line 1715... | Line 1725... | ||
1715 | } |
1725 | } |
1716 | } |
1726 | } |
1717 | card_res->count_fbs = fb_count; |
1727 | card_res->count_fbs = fb_count; |
1718 | mutex_unlock(&file_priv->fbs_lock); |
1728 | mutex_unlock(&file_priv->fbs_lock); |
Line -... | Line 1729... | ||
- | 1729 | ||
- | 1730 | /* mode_config.mutex protects the connector list against e.g. DP MST |
|
1719 | 1731 | * connector hot-adding. CRTC/Plane lists are invariant. */ |
|
1720 | drm_modeset_lock_all(dev); |
1732 | mutex_lock(&dev->mode_config.mutex); |
Line 1721... | Line 1733... | ||
1721 | if (!drm_is_primary_client(file_priv)) { |
1733 | if (!drm_is_primary_client(file_priv)) { |
1722 | 1734 | ||
1723 | mode_group = NULL; |
1735 | mode_group = NULL; |
Line 1835... | Line 1847... | ||
1835 | 1847 | ||
1836 | DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, |
1848 | DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, |
Line 1837... | Line 1849... | ||
1837 | card_res->count_connectors, card_res->count_encoders); |
1849 | card_res->count_connectors, card_res->count_encoders); |
1838 | 1850 | ||
1839 | out: |
1851 | out: |
1840 | drm_modeset_unlock_all(dev); |
1852 | mutex_unlock(&dev->mode_config.mutex); |
Line 1841... | Line 1853... | ||
1841 | return ret; |
1853 | return ret; |
1842 | } |
1854 | } |
Line 1850... | Line 1862... | ||
1850 | * Construct a CRTC configuration structure to return to the user. |
1862 | * Construct a CRTC configuration structure to return to the user. |
1851 | * |
1863 | * |
1852 | * Called by the user via ioctl. |
1864 | * Called by the user via ioctl. |
1853 | * |
1865 | * |
1854 | * Returns: |
1866 | * Returns: |
1855 | * Zero on success, errno on failure. |
1867 | * Zero on success, negative errno on failure. |
1856 | */ |
1868 | */ |
1857 | int drm_mode_getcrtc(struct drm_device *dev, |
1869 | int drm_mode_getcrtc(struct drm_device *dev, |
1858 | void *data, struct drm_file *file_priv) |
1870 | void *data, struct drm_file *file_priv) |
1859 | { |
1871 | { |
1860 | struct drm_mode_crtc *crtc_resp = data; |
1872 | struct drm_mode_crtc *crtc_resp = data; |
1861 | struct drm_crtc *crtc; |
1873 | struct drm_crtc *crtc; |
1862 | int ret = 0; |
- | |
Line 1863... | Line 1874... | ||
1863 | 1874 | ||
1864 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
1875 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 1865... | Line -... | ||
1865 | return -EINVAL; |
- | |
1866 | - | ||
1867 | drm_modeset_lock_all(dev); |
1876 | return -EINVAL; |
1868 | 1877 | ||
1869 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); |
1878 | crtc = drm_crtc_find(dev, crtc_resp->crtc_id); |
1870 | if (!crtc) { |
- | |
1871 | ret = -ENOENT; |
- | |
Line -... | Line 1879... | ||
- | 1879 | if (!crtc) |
|
1872 | goto out; |
1880 | return -ENOENT; |
1873 | } |
1881 | |
1874 | 1882 | drm_modeset_lock_crtc(crtc, crtc->primary); |
|
1875 | crtc_resp->x = crtc->x; |
1883 | crtc_resp->x = crtc->x; |
1876 | crtc_resp->y = crtc->y; |
1884 | crtc_resp->y = crtc->y; |
Line 1886... | Line 1894... | ||
1886 | crtc_resp->mode_valid = 1; |
1894 | crtc_resp->mode_valid = 1; |
Line 1887... | Line 1895... | ||
1887 | 1895 | ||
1888 | } else { |
1896 | } else { |
1889 | crtc_resp->mode_valid = 0; |
1897 | crtc_resp->mode_valid = 0; |
- | 1898 | } |
|
Line 1890... | Line -... | ||
1890 | } |
- | |
1891 | - | ||
1892 | out: |
1899 | drm_modeset_unlock_crtc(crtc); |
1893 | drm_modeset_unlock_all(dev); |
1900 | |
Line 1894... | Line 1901... | ||
1894 | return ret; |
1901 | return 0; |
1895 | } |
1902 | } |
1896 | 1903 | ||
Line 1905... | Line 1912... | ||
1905 | return false; |
1912 | return false; |
Line 1906... | Line 1913... | ||
1906 | 1913 | ||
1907 | return true; |
1914 | return true; |
Line -... | Line 1915... | ||
- | 1915 | } |
|
- | 1916 | ||
- | 1917 | static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector) |
|
- | 1918 | { |
|
- | 1919 | /* For atomic drivers only state objects are synchronously updated and |
|
- | 1920 | * protected by modeset locks, so check those first. */ |
|
- | 1921 | if (connector->state) |
|
- | 1922 | return connector->state->best_encoder; |
|
- | 1923 | return connector->encoder; |
|
1908 | } |
1924 | } |
1909 | 1925 | ||
1910 | /** |
1926 | /** |
1911 | * drm_mode_getconnector - get connector configuration |
1927 | * drm_mode_getconnector - get connector configuration |
1912 | * @dev: drm device for the ioctl |
1928 | * @dev: drm device for the ioctl |
Line 1916... | Line 1932... | ||
1916 | * Construct a connector configuration structure to return to the user. |
1932 | * Construct a connector configuration structure to return to the user. |
1917 | * |
1933 | * |
1918 | * Called by the user via ioctl. |
1934 | * Called by the user via ioctl. |
1919 | * |
1935 | * |
1920 | * Returns: |
1936 | * Returns: |
1921 | * Zero on success, errno on failure. |
1937 | * Zero on success, negative errno on failure. |
1922 | */ |
1938 | */ |
1923 | int drm_mode_getconnector(struct drm_device *dev, void *data, |
1939 | int drm_mode_getconnector(struct drm_device *dev, void *data, |
1924 | struct drm_file *file_priv) |
1940 | struct drm_file *file_priv) |
1925 | { |
1941 | { |
1926 | struct drm_mode_get_connector *out_resp = data; |
1942 | struct drm_mode_get_connector *out_resp = data; |
1927 | struct drm_connector *connector; |
1943 | struct drm_connector *connector; |
- | 1944 | struct drm_encoder *encoder; |
|
1928 | struct drm_display_mode *mode; |
1945 | struct drm_display_mode *mode; |
1929 | int mode_count = 0; |
1946 | int mode_count = 0; |
1930 | int props_count = 0; |
1947 | int props_count = 0; |
1931 | int encoders_count = 0; |
1948 | int encoders_count = 0; |
1932 | int ret = 0; |
1949 | int ret = 0; |
Line 1978... | Line 1995... | ||
1978 | out_resp->mm_width = connector->display_info.width_mm; |
1995 | out_resp->mm_width = connector->display_info.width_mm; |
1979 | out_resp->mm_height = connector->display_info.height_mm; |
1996 | out_resp->mm_height = connector->display_info.height_mm; |
1980 | out_resp->subpixel = connector->display_info.subpixel_order; |
1997 | out_resp->subpixel = connector->display_info.subpixel_order; |
1981 | out_resp->connection = connector->status; |
1998 | out_resp->connection = connector->status; |
1982 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
1999 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
- | 2000 | ||
- | 2001 | encoder = drm_connector_get_encoder(connector); |
|
1983 | if (connector->encoder) |
2002 | if (encoder) |
1984 | out_resp->encoder_id = connector->encoder->base.id; |
2003 | out_resp->encoder_id = encoder->base.id; |
1985 | else |
2004 | else |
1986 | out_resp->encoder_id = 0; |
2005 | out_resp->encoder_id = 0; |
1987 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
2006 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
Line 1988... | Line 2007... | ||
1988 | 2007 | ||
Line 2049... | Line 2068... | ||
2049 | mutex_unlock(&dev->mode_config.mutex); |
2068 | mutex_unlock(&dev->mode_config.mutex); |
Line 2050... | Line 2069... | ||
2050 | 2069 | ||
2051 | return ret; |
2070 | return ret; |
Line -... | Line 2071... | ||
- | 2071 | } |
|
- | 2072 | ||
- | 2073 | static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder) |
|
- | 2074 | { |
|
- | 2075 | struct drm_connector *connector; |
|
- | 2076 | struct drm_device *dev = encoder->dev; |
|
- | 2077 | bool uses_atomic = false; |
|
- | 2078 | ||
- | 2079 | /* For atomic drivers only state objects are synchronously updated and |
|
- | 2080 | * protected by modeset locks, so check those first. */ |
|
- | 2081 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 2082 | if (!connector->state) |
|
- | 2083 | continue; |
|
- | 2084 | ||
- | 2085 | uses_atomic = true; |
|
- | 2086 | ||
- | 2087 | if (connector->state->best_encoder != encoder) |
|
- | 2088 | continue; |
|
- | 2089 | ||
- | 2090 | return connector->state->crtc; |
|
- | 2091 | } |
|
- | 2092 | ||
- | 2093 | /* Don't return stale data (e.g. pending async disable). */ |
|
- | 2094 | if (uses_atomic) |
|
- | 2095 | return NULL; |
|
- | 2096 | ||
- | 2097 | return encoder->crtc; |
|
2052 | } |
2098 | } |
2053 | 2099 | ||
2054 | /** |
2100 | /** |
2055 | * drm_mode_getencoder - get encoder configuration |
2101 | * drm_mode_getencoder - get encoder configuration |
2056 | * @dev: drm device for the ioctl |
2102 | * @dev: drm device for the ioctl |
Line 2060... | Line 2106... | ||
2060 | * Construct a encoder configuration structure to return to the user. |
2106 | * Construct a encoder configuration structure to return to the user. |
2061 | * |
2107 | * |
2062 | * Called by the user via ioctl. |
2108 | * Called by the user via ioctl. |
2063 | * |
2109 | * |
2064 | * Returns: |
2110 | * Returns: |
2065 | * Zero on success, errno on failure. |
2111 | * Zero on success, negative errno on failure. |
2066 | */ |
2112 | */ |
2067 | int drm_mode_getencoder(struct drm_device *dev, void *data, |
2113 | int drm_mode_getencoder(struct drm_device *dev, void *data, |
2068 | struct drm_file *file_priv) |
2114 | struct drm_file *file_priv) |
2069 | { |
2115 | { |
2070 | struct drm_mode_get_encoder *enc_resp = data; |
2116 | struct drm_mode_get_encoder *enc_resp = data; |
2071 | struct drm_encoder *encoder; |
2117 | struct drm_encoder *encoder; |
2072 | int ret = 0; |
2118 | struct drm_crtc *crtc; |
Line 2073... | Line 2119... | ||
2073 | 2119 | ||
2074 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2120 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2075... | Line -... | ||
2075 | return -EINVAL; |
- | |
2076 | 2121 | return -EINVAL; |
|
2077 | drm_modeset_lock_all(dev); |
2122 | |
2078 | encoder = drm_encoder_find(dev, enc_resp->encoder_id); |
2123 | encoder = drm_encoder_find(dev, enc_resp->encoder_id); |
2079 | if (!encoder) { |
- | |
2080 | ret = -ENOENT; |
- | |
Line -... | Line 2124... | ||
- | 2124 | if (!encoder) |
|
- | 2125 | return -ENOENT; |
|
- | 2126 | ||
- | 2127 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); |
|
2081 | goto out; |
2128 | crtc = drm_encoder_get_crtc(encoder); |
2082 | } |
2129 | if (crtc) |
2083 | 2130 | enc_resp->crtc_id = crtc->base.id; |
|
2084 | if (encoder->crtc) |
2131 | else if (encoder->crtc) |
- | 2132 | enc_resp->crtc_id = encoder->crtc->base.id; |
|
- | 2133 | else |
|
2085 | enc_resp->crtc_id = encoder->crtc->base.id; |
2134 | enc_resp->crtc_id = 0; |
2086 | else |
2135 | drm_modeset_unlock(&dev->mode_config.connection_mutex); |
2087 | enc_resp->crtc_id = 0; |
2136 | |
2088 | enc_resp->encoder_type = encoder->encoder_type; |
2137 | enc_resp->encoder_type = encoder->encoder_type; |
Line 2089... | Line -... | ||
2089 | enc_resp->encoder_id = encoder->base.id; |
- | |
2090 | enc_resp->possible_crtcs = encoder->possible_crtcs; |
- | |
2091 | enc_resp->possible_clones = encoder->possible_clones; |
2138 | enc_resp->encoder_id = encoder->base.id; |
2092 | 2139 | enc_resp->possible_crtcs = encoder->possible_crtcs; |
|
Line 2093... | Line 2140... | ||
2093 | out: |
2140 | enc_resp->possible_clones = encoder->possible_clones; |
2094 | drm_modeset_unlock_all(dev); |
2141 | |
2095 | return ret; |
2142 | return 0; |
Line 2104... | Line 2151... | ||
2104 | * Construct a list of plane ids to return to the user. |
2151 | * Construct a list of plane ids to return to the user. |
2105 | * |
2152 | * |
2106 | * Called by the user via ioctl. |
2153 | * Called by the user via ioctl. |
2107 | * |
2154 | * |
2108 | * Returns: |
2155 | * Returns: |
2109 | * Zero on success, errno on failure. |
2156 | * Zero on success, negative errno on failure. |
2110 | */ |
2157 | */ |
2111 | int drm_mode_getplane_res(struct drm_device *dev, void *data, |
2158 | int drm_mode_getplane_res(struct drm_device *dev, void *data, |
2112 | struct drm_file *file_priv) |
2159 | struct drm_file *file_priv) |
2113 | { |
2160 | { |
2114 | struct drm_mode_get_plane_res *plane_resp = data; |
2161 | struct drm_mode_get_plane_res *plane_resp = data; |
2115 | struct drm_mode_config *config; |
2162 | struct drm_mode_config *config; |
2116 | struct drm_plane *plane; |
2163 | struct drm_plane *plane; |
2117 | uint32_t __user *plane_ptr; |
2164 | uint32_t __user *plane_ptr; |
2118 | int copied = 0, ret = 0; |
2165 | int copied = 0; |
2119 | unsigned num_planes; |
2166 | unsigned num_planes; |
Line 2120... | Line 2167... | ||
2120 | 2167 | ||
2121 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2168 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2122... | Line -... | ||
2122 | return -EINVAL; |
- | |
2123 | 2169 | return -EINVAL; |
|
Line 2124... | Line 2170... | ||
2124 | drm_modeset_lock_all(dev); |
2170 | |
2125 | config = &dev->mode_config; |
2171 | config = &dev->mode_config; |
2126 | 2172 | ||
Line 2135... | Line 2181... | ||
2135 | */ |
2181 | */ |
2136 | if (num_planes && |
2182 | if (num_planes && |
2137 | (plane_resp->count_planes >= num_planes)) { |
2183 | (plane_resp->count_planes >= num_planes)) { |
2138 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
2184 | plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; |
Line -... | Line 2185... | ||
- | 2185 | ||
2139 | 2186 | /* Plane lists are invariant, no locking needed. */ |
|
2140 | list_for_each_entry(plane, &config->plane_list, head) { |
2187 | list_for_each_entry(plane, &config->plane_list, head) { |
2141 | /* |
2188 | /* |
2142 | * Unless userspace set the 'universal planes' |
2189 | * Unless userspace set the 'universal planes' |
2143 | * capability bit, only advertise overlays. |
2190 | * capability bit, only advertise overlays. |
2144 | */ |
2191 | */ |
2145 | if (plane->type != DRM_PLANE_TYPE_OVERLAY && |
2192 | if (plane->type != DRM_PLANE_TYPE_OVERLAY && |
2146 | !file_priv->universal_planes) |
2193 | !file_priv->universal_planes) |
Line 2147... | Line 2194... | ||
2147 | continue; |
2194 | continue; |
2148 | 2195 | ||
2149 | if (put_user(plane->base.id, plane_ptr + copied)) { |
- | |
2150 | ret = -EFAULT; |
- | |
2151 | goto out; |
2196 | if (put_user(plane->base.id, plane_ptr + copied)) |
2152 | } |
2197 | return -EFAULT; |
2153 | copied++; |
2198 | copied++; |
2154 | } |
2199 | } |
Line 2155... | Line -... | ||
2155 | } |
- | |
2156 | plane_resp->count_planes = num_planes; |
- | |
2157 | 2200 | } |
|
2158 | out: |
2201 | plane_resp->count_planes = num_planes; |
Line 2159... | Line 2202... | ||
2159 | drm_modeset_unlock_all(dev); |
2202 | |
2160 | return ret; |
2203 | return 0; |
2161 | } |
2204 | } |
Line 2169... | Line 2212... | ||
2169 | * Construct a plane configuration structure to return to the user. |
2212 | * Construct a plane configuration structure to return to the user. |
2170 | * |
2213 | * |
2171 | * Called by the user via ioctl. |
2214 | * Called by the user via ioctl. |
2172 | * |
2215 | * |
2173 | * Returns: |
2216 | * Returns: |
2174 | * Zero on success, errno on failure. |
2217 | * Zero on success, negative errno on failure. |
2175 | */ |
2218 | */ |
2176 | int drm_mode_getplane(struct drm_device *dev, void *data, |
2219 | int drm_mode_getplane(struct drm_device *dev, void *data, |
2177 | struct drm_file *file_priv) |
2220 | struct drm_file *file_priv) |
2178 | { |
2221 | { |
2179 | struct drm_mode_get_plane *plane_resp = data; |
2222 | struct drm_mode_get_plane *plane_resp = data; |
2180 | struct drm_plane *plane; |
2223 | struct drm_plane *plane; |
2181 | uint32_t __user *format_ptr; |
2224 | uint32_t __user *format_ptr; |
2182 | int ret = 0; |
- | |
Line 2183... | Line 2225... | ||
2183 | 2225 | ||
2184 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
2226 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 2185... | Line -... | ||
2185 | return -EINVAL; |
- | |
2186 | 2227 | return -EINVAL; |
|
2187 | drm_modeset_lock_all(dev); |
2228 | |
2188 | plane = drm_plane_find(dev, plane_resp->plane_id); |
2229 | plane = drm_plane_find(dev, plane_resp->plane_id); |
2189 | if (!plane) { |
- | |
2190 | ret = -ENOENT; |
- | |
Line -... | Line 2230... | ||
- | 2230 | if (!plane) |
|
2191 | goto out; |
2231 | return -ENOENT; |
2192 | } |
2232 | |
2193 | 2233 | drm_modeset_lock(&plane->mutex, NULL); |
|
2194 | if (plane->crtc) |
2234 | if (plane->crtc) |
Line 2195... | Line 2235... | ||
2195 | plane_resp->crtc_id = plane->crtc->base.id; |
2235 | plane_resp->crtc_id = plane->crtc->base.id; |
2196 | else |
2236 | else |
2197 | plane_resp->crtc_id = 0; |
2237 | plane_resp->crtc_id = 0; |
2198 | 2238 | ||
- | 2239 | if (plane->fb) |
|
Line 2199... | Line 2240... | ||
2199 | if (plane->fb) |
2240 | plane_resp->fb_id = plane->fb->base.id; |
2200 | plane_resp->fb_id = plane->fb->base.id; |
2241 | else |
2201 | else |
2242 | plane_resp->fb_id = 0; |
Line 2213... | Line 2254... | ||
2213 | (plane_resp->count_format_types >= plane->format_count)) { |
2254 | (plane_resp->count_format_types >= plane->format_count)) { |
2214 | format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; |
2255 | format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; |
2215 | if (copy_to_user(format_ptr, |
2256 | if (copy_to_user(format_ptr, |
2216 | plane->format_types, |
2257 | plane->format_types, |
2217 | sizeof(uint32_t) * plane->format_count)) { |
2258 | sizeof(uint32_t) * plane->format_count)) { |
2218 | ret = -EFAULT; |
2259 | return -EFAULT; |
2219 | goto out; |
- | |
2220 | } |
2260 | } |
2221 | } |
2261 | } |
2222 | plane_resp->count_format_types = plane->format_count; |
2262 | plane_resp->count_format_types = plane->format_count; |
Line 2223... | Line -... | ||
2223 | - | ||
2224 | out: |
- | |
2225 | drm_modeset_unlock_all(dev); |
2263 | |
2226 | return ret; |
2264 | return 0; |
Line 2227... | Line 2265... | ||
2227 | } |
2265 | } |
2228 | 2266 | ||
2229 | /* |
2267 | /* |
Line 2233... | Line 2271... | ||
2233 | * update fails, this reference will be dropped before return; if it succeeds, |
2271 | * update fails, this reference will be dropped before return; if it succeeds, |
2234 | * the previous framebuffer (if any) will be unreferenced instead. |
2272 | * the previous framebuffer (if any) will be unreferenced instead. |
2235 | * |
2273 | * |
2236 | * src_{x,y,w,h} are provided in 16.16 fixed point format |
2274 | * src_{x,y,w,h} are provided in 16.16 fixed point format |
2237 | */ |
2275 | */ |
2238 | static int setplane_internal(struct drm_plane *plane, |
2276 | static int __setplane_internal(struct drm_plane *plane, |
2239 | struct drm_crtc *crtc, |
2277 | struct drm_crtc *crtc, |
2240 | struct drm_framebuffer *fb, |
2278 | struct drm_framebuffer *fb, |
2241 | int32_t crtc_x, int32_t crtc_y, |
2279 | int32_t crtc_x, int32_t crtc_y, |
2242 | uint32_t crtc_w, uint32_t crtc_h, |
2280 | uint32_t crtc_w, uint32_t crtc_h, |
2243 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
2281 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
2244 | uint32_t src_x, uint32_t src_y, |
2282 | uint32_t src_x, uint32_t src_y, |
2245 | uint32_t src_w, uint32_t src_h) |
2283 | uint32_t src_w, uint32_t src_h) |
2246 | { |
2284 | { |
2247 | struct drm_device *dev = plane->dev; |
- | |
2248 | struct drm_framebuffer *old_fb = NULL; |
- | |
2249 | int ret = 0; |
2285 | int ret = 0; |
2250 | unsigned int fb_width, fb_height; |
2286 | unsigned int fb_width, fb_height; |
2251 | int i; |
2287 | unsigned int i; |
Line 2252... | Line 2288... | ||
2252 | 2288 | ||
2253 | /* No fb means shut it down */ |
2289 | /* No fb means shut it down */ |
2254 | if (!fb) { |
- | |
2255 | drm_modeset_lock_all(dev); |
2290 | if (!fb) { |
2256 | old_fb = plane->fb; |
2291 | plane->old_fb = plane->fb; |
2257 | ret = plane->funcs->disable_plane(plane); |
2292 | ret = plane->funcs->disable_plane(plane); |
2258 | if (!ret) { |
2293 | if (!ret) { |
2259 | plane->crtc = NULL; |
2294 | plane->crtc = NULL; |
2260 | plane->fb = NULL; |
2295 | plane->fb = NULL; |
2261 | } else { |
2296 | } else { |
2262 | old_fb = NULL; |
2297 | plane->old_fb = NULL; |
2263 | } |
- | |
2264 | drm_modeset_unlock_all(dev); |
2298 | } |
2265 | goto out; |
2299 | goto out; |
Line 2266... | Line 2300... | ||
2266 | } |
2300 | } |
2267 | 2301 | ||
Line 2299... | Line 2333... | ||
2299 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); |
2333 | src_y >> 16, ((src_y & 0xffff) * 15625) >> 10); |
2300 | ret = -ENOSPC; |
2334 | ret = -ENOSPC; |
2301 | goto out; |
2335 | goto out; |
2302 | } |
2336 | } |
Line 2303... | Line -... | ||
2303 | - | ||
2304 | drm_modeset_lock_all(dev); |
2337 | |
2305 | old_fb = plane->fb; |
2338 | plane->old_fb = plane->fb; |
2306 | ret = plane->funcs->update_plane(plane, crtc, fb, |
2339 | ret = plane->funcs->update_plane(plane, crtc, fb, |
2307 | crtc_x, crtc_y, crtc_w, crtc_h, |
2340 | crtc_x, crtc_y, crtc_w, crtc_h, |
2308 | src_x, src_y, src_w, src_h); |
2341 | src_x, src_y, src_w, src_h); |
2309 | if (!ret) { |
2342 | if (!ret) { |
2310 | plane->crtc = crtc; |
2343 | plane->crtc = crtc; |
2311 | plane->fb = fb; |
2344 | plane->fb = fb; |
2312 | fb = NULL; |
2345 | fb = NULL; |
2313 | } else { |
2346 | } else { |
2314 | old_fb = NULL; |
2347 | plane->old_fb = NULL; |
2315 | } |
- | |
Line 2316... | Line 2348... | ||
2316 | drm_modeset_unlock_all(dev); |
2348 | } |
2317 | 2349 | ||
2318 | out: |
2350 | out: |
2319 | if (fb) |
2351 | if (fb) |
2320 | drm_framebuffer_unreference(fb); |
2352 | drm_framebuffer_unreference(fb); |
- | 2353 | if (plane->old_fb) |
|
Line 2321... | Line 2354... | ||
2321 | if (old_fb) |
2354 | drm_framebuffer_unreference(plane->old_fb); |
- | 2355 | plane->old_fb = NULL; |
|
Line -... | Line 2356... | ||
- | 2356 | ||
- | 2357 | return ret; |
|
- | 2358 | } |
|
- | 2359 | ||
- | 2360 | static int setplane_internal(struct drm_plane *plane, |
|
- | 2361 | struct drm_crtc *crtc, |
|
- | 2362 | struct drm_framebuffer *fb, |
|
- | 2363 | int32_t crtc_x, int32_t crtc_y, |
|
- | 2364 | uint32_t crtc_w, uint32_t crtc_h, |
|
- | 2365 | /* src_{x,y,w,h} values are 16.16 fixed point */ |
|
- | 2366 | uint32_t src_x, uint32_t src_y, |
|
- | 2367 | uint32_t src_w, uint32_t src_h) |
|
- | 2368 | { |
|
- | 2369 | int ret; |
|
- | 2370 | ||
- | 2371 | drm_modeset_lock_all(plane->dev); |
|
- | 2372 | ret = __setplane_internal(plane, crtc, fb, |
|
- | 2373 | crtc_x, crtc_y, crtc_w, crtc_h, |
|
2322 | drm_framebuffer_unreference(old_fb); |
2374 | src_x, src_y, src_w, src_h); |
Line 2323... | Line 2375... | ||
2323 | 2375 | drm_modeset_unlock_all(plane->dev); |
|
2324 | return ret; |
2376 | |
2325 | 2377 | return ret; |
|
Line 2334... | Line 2386... | ||
2334 | * Set plane configuration, including placement, fb, scaling, and other factors. |
2386 | * Set plane configuration, including placement, fb, scaling, and other factors. |
2335 | * Or pass a NULL fb to disable (planes may be disabled without providing a |
2387 | * Or pass a NULL fb to disable (planes may be disabled without providing a |
2336 | * valid crtc). |
2388 | * valid crtc). |
2337 | * |
2389 | * |
2338 | * Returns: |
2390 | * Returns: |
2339 | * Zero on success, errno on failure. |
2391 | * Zero on success, negative errno on failure. |
2340 | */ |
2392 | */ |
2341 | int drm_mode_setplane(struct drm_device *dev, void *data, |
2393 | int drm_mode_setplane(struct drm_device *dev, void *data, |
2342 | struct drm_file *file_priv) |
2394 | struct drm_file *file_priv) |
2343 | { |
2395 | { |
2344 | struct drm_mode_set_plane *plane_req = data; |
2396 | struct drm_mode_set_plane *plane_req = data; |
2345 | struct drm_mode_object *obj; |
- | |
2346 | struct drm_plane *plane; |
2397 | struct drm_plane *plane; |
2347 | struct drm_crtc *crtc = NULL; |
2398 | struct drm_crtc *crtc = NULL; |
2348 | struct drm_framebuffer *fb = NULL; |
2399 | struct drm_framebuffer *fb = NULL; |
Line 2349... | Line 2400... | ||
2349 | 2400 | ||
Line 2363... | Line 2414... | ||
2363 | 2414 | ||
2364 | /* |
2415 | /* |
2365 | * First, find the plane, crtc, and fb objects. If not available, |
2416 | * First, find the plane, crtc, and fb objects. If not available, |
2366 | * we don't bother to call the driver. |
2417 | * we don't bother to call the driver. |
2367 | */ |
2418 | */ |
2368 | obj = drm_mode_object_find(dev, plane_req->plane_id, |
- | |
2369 | DRM_MODE_OBJECT_PLANE); |
2419 | plane = drm_plane_find(dev, plane_req->plane_id); |
2370 | if (!obj) { |
2420 | if (!plane) { |
2371 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
2421 | DRM_DEBUG_KMS("Unknown plane ID %d\n", |
2372 | plane_req->plane_id); |
2422 | plane_req->plane_id); |
2373 | return -ENOENT; |
2423 | return -ENOENT; |
2374 | } |
- | |
Line 2375... | Line 2424... | ||
2375 | plane = obj_to_plane(obj); |
2424 | } |
2376 | 2425 | ||
2377 | if (plane_req->fb_id) { |
2426 | if (plane_req->fb_id) { |
2378 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); |
2427 | fb = drm_framebuffer_lookup(dev, plane_req->fb_id); |
2379 | if (!fb) { |
2428 | if (!fb) { |
2380 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", |
2429 | DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", |
2381 | plane_req->fb_id); |
2430 | plane_req->fb_id); |
Line 2382... | Line 2431... | ||
2382 | return -ENOENT; |
2431 | return -ENOENT; |
2383 | } |
- | |
2384 | 2432 | } |
|
2385 | obj = drm_mode_object_find(dev, plane_req->crtc_id, |
2433 | |
2386 | DRM_MODE_OBJECT_CRTC); |
2434 | crtc = drm_crtc_find(dev, plane_req->crtc_id); |
2387 | if (!obj) { |
2435 | if (!crtc) { |
2388 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", |
2436 | DRM_DEBUG_KMS("Unknown crtc ID %d\n", |
2389 | plane_req->crtc_id); |
- | |
2390 | return -ENOENT; |
2437 | plane_req->crtc_id); |
Line 2391... | Line 2438... | ||
2391 | } |
2438 | return -ENOENT; |
2392 | crtc = obj_to_crtc(obj); |
2439 | } |
2393 | } |
2440 | } |
Line 2410... | Line 2457... | ||
2410 | * |
2457 | * |
2411 | * This is a little helper to wrap internal calls to the ->set_config driver |
2458 | * This is a little helper to wrap internal calls to the ->set_config driver |
2412 | * interface. The only thing it adds is correct refcounting dance. |
2459 | * interface. The only thing it adds is correct refcounting dance. |
2413 | * |
2460 | * |
2414 | * Returns: |
2461 | * Returns: |
2415 | * Zero on success, errno on failure. |
2462 | * Zero on success, negative errno on failure. |
2416 | */ |
2463 | */ |
2417 | int drm_mode_set_config_internal(struct drm_mode_set *set) |
2464 | int drm_mode_set_config_internal(struct drm_mode_set *set) |
2418 | { |
2465 | { |
2419 | struct drm_crtc *crtc = set->crtc; |
2466 | struct drm_crtc *crtc = set->crtc; |
2420 | struct drm_framebuffer *fb; |
2467 | struct drm_framebuffer *fb; |
Line 2425... | Line 2472... | ||
2425 | * NOTE: ->set_config can also disable other crtcs (if we steal all |
2472 | * NOTE: ->set_config can also disable other crtcs (if we steal all |
2426 | * connectors from it), hence we need to refcount the fbs across all |
2473 | * connectors from it), hence we need to refcount the fbs across all |
2427 | * crtcs. Atomic modeset will have saner semantics ... |
2474 | * crtcs. Atomic modeset will have saner semantics ... |
2428 | */ |
2475 | */ |
2429 | list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) |
2476 | list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) |
2430 | tmp->old_fb = tmp->primary->fb; |
2477 | tmp->primary->old_fb = tmp->primary->fb; |
Line 2431... | Line 2478... | ||
2431 | 2478 | ||
Line 2432... | Line 2479... | ||
2432 | fb = set->fb; |
2479 | fb = set->fb; |
2433 | 2480 | ||
Line 2503... | Line 2550... | ||
2503 | * Build a new CRTC configuration based on user request. |
2550 | * Build a new CRTC configuration based on user request. |
2504 | * |
2551 | * |
2505 | * Called by the user via ioctl. |
2552 | * Called by the user via ioctl. |
2506 | * |
2553 | * |
2507 | * Returns: |
2554 | * Returns: |
2508 | * Zero on success, errno on failure. |
2555 | * Zero on success, negative errno on failure. |
2509 | */ |
2556 | */ |
2510 | int drm_mode_setcrtc(struct drm_device *dev, void *data, |
2557 | int drm_mode_setcrtc(struct drm_device *dev, void *data, |
2511 | struct drm_file *file_priv) |
2558 | struct drm_file *file_priv) |
2512 | { |
2559 | { |
2513 | struct drm_mode_config *config = &dev->mode_config; |
2560 | struct drm_mode_config *config = &dev->mode_config; |
Line 2672... | Line 2719... | ||
2672 | 2719 | ||
2673 | /* |
2720 | /* |
2674 | * If this crtc has a universal cursor plane, call that plane's update |
2721 | * If this crtc has a universal cursor plane, call that plane's update |
2675 | * handler rather than using legacy cursor handlers. |
2722 | * handler rather than using legacy cursor handlers. |
- | 2723 | */ |
|
2676 | */ |
2724 | drm_modeset_lock_crtc(crtc, crtc->cursor); |
2677 | if (crtc->cursor) |
2725 | if (crtc->cursor) { |
- | 2726 | ret = drm_mode_cursor_universal(crtc, req, file_priv); |
|
- | 2727 | goto out; |
|
Line 2678... | Line -... | ||
2678 | return drm_mode_cursor_universal(crtc, req, file_priv); |
- | |
2679 | 2728 | } |
|
2680 | drm_modeset_lock(&crtc->mutex, NULL); |
2729 | |
2681 | if (req->flags & DRM_MODE_CURSOR_BO) { |
2730 | if (req->flags & DRM_MODE_CURSOR_BO) { |
2682 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { |
2731 | if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { |
2683 | ret = -ENXIO; |
2732 | ret = -ENXIO; |
Line 2699... | Line 2748... | ||
2699 | ret = -EFAULT; |
2748 | ret = -EFAULT; |
2700 | goto out; |
2749 | goto out; |
2701 | } |
2750 | } |
2702 | } |
2751 | } |
2703 | out: |
2752 | out: |
2704 | drm_modeset_unlock(&crtc->mutex); |
2753 | drm_modeset_unlock_crtc(crtc); |
Line 2705... | Line 2754... | ||
2705 | 2754 | ||
Line 2706... | Line 2755... | ||
2706 | return ret; |
2755 | return ret; |
Line 2717... | Line 2766... | ||
2717 | * Set the cursor configuration based on user request. |
2766 | * Set the cursor configuration based on user request. |
2718 | * |
2767 | * |
2719 | * Called by the user via ioctl. |
2768 | * Called by the user via ioctl. |
2720 | * |
2769 | * |
2721 | * Returns: |
2770 | * Returns: |
2722 | * Zero on success, errno on failure. |
2771 | * Zero on success, negative errno on failure. |
2723 | */ |
2772 | */ |
2724 | int drm_mode_cursor_ioctl(struct drm_device *dev, |
2773 | int drm_mode_cursor_ioctl(struct drm_device *dev, |
2725 | void *data, struct drm_file *file_priv) |
2774 | void *data, struct drm_file *file_priv) |
2726 | { |
2775 | { |
2727 | struct drm_mode_cursor *req = data; |
2776 | struct drm_mode_cursor *req = data; |
Line 2744... | Line 2793... | ||
2744 | * the hotspot of the pointer. |
2793 | * the hotspot of the pointer. |
2745 | * |
2794 | * |
2746 | * Called by the user via ioctl. |
2795 | * Called by the user via ioctl. |
2747 | * |
2796 | * |
2748 | * Returns: |
2797 | * Returns: |
2749 | * Zero on success, errno on failure. |
2798 | * Zero on success, negative errno on failure. |
2750 | */ |
2799 | */ |
2751 | int drm_mode_cursor2_ioctl(struct drm_device *dev, |
2800 | int drm_mode_cursor2_ioctl(struct drm_device *dev, |
2752 | void *data, struct drm_file *file_priv) |
2801 | void *data, struct drm_file *file_priv) |
2753 | { |
2802 | { |
2754 | struct drm_mode_cursor2 *req = data; |
2803 | struct drm_mode_cursor2 *req = data; |
Line 2804... | Line 2853... | ||
2804 | * @dev: drm device for the ioctl |
2853 | * @dev: drm device for the ioctl |
2805 | * @data: data pointer for the ioctl |
2854 | * @data: data pointer for the ioctl |
2806 | * @file_priv: drm file for the ioctl call |
2855 | * @file_priv: drm file for the ioctl call |
2807 | * |
2856 | * |
2808 | * Add a new FB to the specified CRTC, given a user request. This is the |
2857 | * Add a new FB to the specified CRTC, given a user request. This is the |
2809 | * original addfb ioclt which only supported RGB formats. |
2858 | * original addfb ioctl which only supported RGB formats. |
2810 | * |
2859 | * |
2811 | * Called by the user via ioctl. |
2860 | * Called by the user via ioctl. |
2812 | * |
2861 | * |
2813 | * Returns: |
2862 | * Returns: |
2814 | * Zero on success, errno on failure. |
2863 | * Zero on success, negative errno on failure. |
2815 | */ |
2864 | */ |
2816 | int drm_mode_addfb(struct drm_device *dev, |
2865 | int drm_mode_addfb(struct drm_device *dev, |
2817 | void *data, struct drm_file *file_priv) |
2866 | void *data, struct drm_file *file_priv) |
2818 | { |
2867 | { |
2819 | struct drm_mode_fb_cmd *or = data; |
2868 | struct drm_mode_fb_cmd *or = data; |
2820 | struct drm_mode_fb_cmd2 r = {}; |
2869 | struct drm_mode_fb_cmd2 r = {}; |
2821 | struct drm_mode_config *config = &dev->mode_config; |
- | |
2822 | struct drm_framebuffer *fb; |
- | |
2823 | int ret = 0; |
2870 | int ret; |
Line 2824... | Line 2871... | ||
2824 | 2871 | ||
2825 | /* Use new struct with format internally */ |
2872 | /* convert to new format and call new ioctl */ |
2826 | r.fb_id = or->fb_id; |
2873 | r.fb_id = or->fb_id; |
2827 | r.width = or->width; |
2874 | r.width = or->width; |
2828 | r.height = or->height; |
2875 | r.height = or->height; |
2829 | r.pitches[0] = or->pitch; |
2876 | r.pitches[0] = or->pitch; |
2830 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
2877 | r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); |
Line 2831... | Line -... | ||
2831 | r.handles[0] = or->handle; |
- | |
2832 | - | ||
2833 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
- | |
2834 | return -EINVAL; |
- | |
2835 | - | ||
2836 | if ((config->min_width > r.width) || (r.width > config->max_width)) |
- | |
2837 | return -EINVAL; |
- | |
2838 | - | ||
2839 | if ((config->min_height > r.height) || (r.height > config->max_height)) |
- | |
2840 | return -EINVAL; |
2878 | r.handles[0] = or->handle; |
2841 | 2879 | ||
2842 | fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); |
- | |
2843 | if (IS_ERR(fb)) { |
2880 | ret = drm_mode_addfb2(dev, &r, file_priv); |
2844 | DRM_DEBUG_KMS("could not create framebuffer\n"); |
- | |
Line 2845... | Line -... | ||
2845 | return PTR_ERR(fb); |
- | |
2846 | } |
2881 | if (ret) |
2847 | - | ||
2848 | mutex_lock(&file_priv->fbs_lock); |
- | |
2849 | or->fb_id = fb->base.id; |
- | |
Line 2850... | Line 2882... | ||
2850 | list_add(&fb->filp_head, &file_priv->fbs); |
2882 | return ret; |
2851 | DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); |
2883 | |
Line 2852... | Line 2884... | ||
2852 | mutex_unlock(&file_priv->fbs_lock); |
2884 | or->fb_id = r.fb_id; |
2853 | 2885 | ||
2854 | return ret; |
2886 | return 0; |
Line 2941... | Line 2973... | ||
2941 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); |
2973 | hsub = drm_format_horz_chroma_subsampling(r->pixel_format); |
2942 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); |
2974 | vsub = drm_format_vert_chroma_subsampling(r->pixel_format); |
2943 | num_planes = drm_format_num_planes(r->pixel_format); |
2975 | num_planes = drm_format_num_planes(r->pixel_format); |
Line 2944... | Line 2976... | ||
2944 | 2976 | ||
2945 | if (r->width == 0 || r->width % hsub) { |
2977 | if (r->width == 0 || r->width % hsub) { |
2946 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); |
2978 | DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width); |
2947 | return -EINVAL; |
2979 | return -EINVAL; |
Line 2948... | Line 2980... | ||
2948 | } |
2980 | } |
2949 | 2981 | ||
Line 3031... | Line 3063... | ||
3031 | * and uses fourcc codes as pixel format specifiers. |
3063 | * and uses fourcc codes as pixel format specifiers. |
3032 | * |
3064 | * |
3033 | * Called by the user via ioctl. |
3065 | * Called by the user via ioctl. |
3034 | * |
3066 | * |
3035 | * Returns: |
3067 | * Returns: |
3036 | * Zero on success, errno on failure. |
3068 | * Zero on success, negative errno on failure. |
3037 | */ |
3069 | */ |
3038 | int drm_mode_addfb2(struct drm_device *dev, |
3070 | int drm_mode_addfb2(struct drm_device *dev, |
3039 | void *data, struct drm_file *file_priv) |
3071 | void *data, struct drm_file *file_priv) |
3040 | { |
3072 | { |
3041 | struct drm_framebuffer *fb; |
3073 | struct drm_framebuffer *fb; |
Line 3059... | Line 3091... | ||
3059 | * Remove the FB specified by the user. |
3091 | * Remove the FB specified by the user. |
3060 | * |
3092 | * |
3061 | * Called by the user via ioctl. |
3093 | * Called by the user via ioctl. |
3062 | * |
3094 | * |
3063 | * Returns: |
3095 | * Returns: |
3064 | * Zero on success, errno on failure. |
3096 | * Zero on success, negative errno on failure. |
3065 | */ |
3097 | */ |
3066 | int drm_mode_rmfb(struct drm_device *dev, |
3098 | int drm_mode_rmfb(struct drm_device *dev, |
3067 | void *data, struct drm_file *file_priv) |
3099 | void *data, struct drm_file *file_priv) |
3068 | { |
3100 | { |
3069 | struct drm_framebuffer *fb = NULL; |
3101 | struct drm_framebuffer *fb = NULL; |
Line 3113... | Line 3145... | ||
3113 | * Lookup the FB given its ID and return info about it. |
3145 | * Lookup the FB given its ID and return info about it. |
3114 | * |
3146 | * |
3115 | * Called by the user via ioctl. |
3147 | * Called by the user via ioctl. |
3116 | * |
3148 | * |
3117 | * Returns: |
3149 | * Returns: |
3118 | * Zero on success, errno on failure. |
3150 | * Zero on success, negative errno on failure. |
3119 | */ |
3151 | */ |
3120 | int drm_mode_getfb(struct drm_device *dev, |
3152 | int drm_mode_getfb(struct drm_device *dev, |
3121 | void *data, struct drm_file *file_priv) |
3153 | void *data, struct drm_file *file_priv) |
3122 | { |
3154 | { |
3123 | struct drm_mode_fb_cmd *r = data; |
3155 | struct drm_mode_fb_cmd *r = data; |
Line 3135... | Line 3167... | ||
3135 | r->width = fb->width; |
3167 | r->width = fb->width; |
3136 | r->depth = fb->depth; |
3168 | r->depth = fb->depth; |
3137 | r->bpp = fb->bits_per_pixel; |
3169 | r->bpp = fb->bits_per_pixel; |
3138 | r->pitch = fb->pitches[0]; |
3170 | r->pitch = fb->pitches[0]; |
3139 | if (fb->funcs->create_handle) { |
3171 | if (fb->funcs->create_handle) { |
3140 | if (file_priv->is_master || capable(CAP_SYS_ADMIN)) { |
3172 | if (file_priv->is_master || capable(CAP_SYS_ADMIN) || |
- | 3173 | drm_is_control_client(file_priv)) { |
|
3141 | ret = fb->funcs->create_handle(fb, file_priv, |
3174 | ret = fb->funcs->create_handle(fb, file_priv, |
3142 | &r->handle); |
3175 | &r->handle); |
3143 | } else { |
3176 | } else { |
3144 | /* GET_FB() is an unprivileged ioctl so we must not |
3177 | /* GET_FB() is an unprivileged ioctl so we must not |
3145 | * return a buffer-handle to non-master processes! For |
3178 | * return a buffer-handle to non-master processes! For |
Line 3173... | Line 3206... | ||
3173 | * implement the corresponding ->dirty framebuffer callback. |
3206 | * implement the corresponding ->dirty framebuffer callback. |
3174 | * |
3207 | * |
3175 | * Called by the user via ioctl. |
3208 | * Called by the user via ioctl. |
3176 | * |
3209 | * |
3177 | * Returns: |
3210 | * Returns: |
3178 | * Zero on success, errno on failure. |
3211 | * Zero on success, negative errno on failure. |
3179 | */ |
3212 | */ |
3180 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, |
3213 | int drm_mode_dirtyfb_ioctl(struct drm_device *dev, |
3181 | void *data, struct drm_file *file_priv) |
3214 | void *data, struct drm_file *file_priv) |
3182 | { |
3215 | { |
3183 | struct drm_clip_rect __user *clips_ptr; |
3216 | struct drm_clip_rect __user *clips_ptr; |
Line 3253... | Line 3286... | ||
3253 | * Destroy all the FBs associated with @filp. |
3286 | * Destroy all the FBs associated with @filp. |
3254 | * |
3287 | * |
3255 | * Called by the user via ioctl. |
3288 | * Called by the user via ioctl. |
3256 | * |
3289 | * |
3257 | * Returns: |
3290 | * Returns: |
3258 | * Zero on success, errno on failure. |
3291 | * Zero on success, negative errno on failure. |
3259 | */ |
3292 | */ |
3260 | void drm_fb_release(struct drm_file *priv) |
3293 | void drm_fb_release(struct drm_file *priv) |
3261 | { |
3294 | { |
3262 | struct drm_device *dev = priv->minor->dev; |
3295 | struct drm_device *dev = priv->minor->dev; |
3263 | struct drm_framebuffer *fb, *tfb; |
3296 | struct drm_framebuffer *fb, *tfb; |
Line -... | Line 3297... | ||
- | 3297 | ||
- | 3298 | /* |
|
- | 3299 | * When the file gets released that means no one else can access the fb |
|
- | 3300 | * list any more, so no need to grab fpriv->fbs_lock. And we need to |
|
3264 | 3301 | * avoid upsetting lockdep since the universal cursor code adds a |
|
- | 3302 | * framebuffer while holding mutex locks. |
|
- | 3303 | * |
|
- | 3304 | * 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 |
|
- | 3306 | * at it any more. |
|
3265 | mutex_lock(&priv->fbs_lock); |
3307 | */ |
Line 3266... | Line 3308... | ||
3266 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
3308 | list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { |
3267 | 3309 | ||
3268 | mutex_lock(&dev->mode_config.fb_lock); |
3310 | mutex_lock(&dev->mode_config.fb_lock); |
Line 3273... | Line 3315... | ||
3273 | list_del_init(&fb->filp_head); |
3315 | list_del_init(&fb->filp_head); |
Line 3274... | Line 3316... | ||
3274 | 3316 | ||
3275 | /* This will also drop the fpriv->fbs reference. */ |
3317 | /* This will also drop the fpriv->fbs reference. */ |
3276 | drm_framebuffer_remove(fb); |
3318 | drm_framebuffer_remove(fb); |
3277 | } |
- | |
3278 | mutex_unlock(&priv->fbs_lock); |
3319 | } |
3279 | } |
3320 | } |
Line 3280... | Line 3321... | ||
3280 | #endif |
3321 | #endif |
Line 3289... | Line 3330... | ||
3289 | * |
3330 | * |
3290 | * This creates a new generic drm property which can then be attached to a drm |
3331 | * This creates a new generic drm property which can then be attached to a drm |
3291 | * object with drm_object_attach_property. The returned property object must be |
3332 | * object with drm_object_attach_property. The returned property object must be |
3292 | * freed with drm_property_destroy. |
3333 | * freed with drm_property_destroy. |
3293 | * |
3334 | * |
- | 3335 | * Note that the DRM core keeps a per-device list of properties and that, if |
|
- | 3336 | * drm_mode_config_cleanup() is called, it will destroy all properties created |
|
- | 3337 | * by the driver. |
|
- | 3338 | * |
|
3294 | * Returns: |
3339 | * Returns: |
3295 | * A pointer to the newly created property on success, NULL on failure. |
3340 | * A pointer to the newly created property on success, NULL on failure. |
3296 | */ |
3341 | */ |
3297 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, |
3342 | struct drm_property *drm_property_create(struct drm_device *dev, int flags, |
3298 | const char *name, int num_values) |
3343 | const char *name, int num_values) |
Line 3316... | Line 3361... | ||
3316 | if (ret) |
3361 | if (ret) |
3317 | goto fail; |
3362 | goto fail; |
Line 3318... | Line 3363... | ||
3318 | 3363 | ||
3319 | property->flags = flags; |
3364 | property->flags = flags; |
3320 | property->num_values = num_values; |
3365 | property->num_values = num_values; |
Line 3321... | Line 3366... | ||
3321 | INIT_LIST_HEAD(&property->enum_blob_list); |
3366 | INIT_LIST_HEAD(&property->enum_list); |
3322 | 3367 | ||
3323 | if (name) { |
3368 | if (name) { |
3324 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
3369 | strncpy(property->name, name, DRM_PROP_NAME_LEN); |
Line 3387... | Line 3432... | ||
3387 | * drm_property_create_bitmask - create a new bitmask property type |
3432 | * drm_property_create_bitmask - create a new bitmask property type |
3388 | * @dev: drm device |
3433 | * @dev: drm device |
3389 | * @flags: flags specifying the property type |
3434 | * @flags: flags specifying the property type |
3390 | * @name: name of the property |
3435 | * @name: name of the property |
3391 | * @props: enumeration lists with property bitflags |
3436 | * @props: enumeration lists with property bitflags |
3392 | * @num_values: number of pre-defined values |
3437 | * @num_props: size of the @props array |
- | 3438 | * @supported_bits: bitmask of all supported enumeration values |
|
3393 | * |
3439 | * |
3394 | * This creates a new generic drm property which can then be attached to a drm |
3440 | * This creates a new bitmask drm property which can then be attached to a drm |
3395 | * object with drm_object_attach_property. The returned property object must be |
3441 | * object with drm_object_attach_property. The returned property object must be |
3396 | * freed with drm_property_destroy. |
3442 | * freed with drm_property_destroy. |
3397 | * |
3443 | * |
3398 | * Compared to plain enumeration properties userspace is allowed to set any |
3444 | * Compared to plain enumeration properties userspace is allowed to set any |
3399 | * or'ed together combination of the predefined property bitflag values |
3445 | * or'ed together combination of the predefined property bitflag values |
Line 3464... | Line 3510... | ||
3464 | * |
3510 | * |
3465 | * This creates a new generic drm property which can then be attached to a drm |
3511 | * This creates a new generic drm property which can then be attached to a drm |
3466 | * object with drm_object_attach_property. The returned property object must be |
3512 | * object with drm_object_attach_property. The returned property object must be |
3467 | * freed with drm_property_destroy. |
3513 | * freed with drm_property_destroy. |
3468 | * |
3514 | * |
3469 | * Userspace is allowed to set any interger value in the (min, max) range |
3515 | * Userspace is allowed to set any integer value in the (min, max) range |
3470 | * inclusive. |
3516 | * inclusive. |
3471 | * |
3517 | * |
3472 | * Returns: |
3518 | * Returns: |
3473 | * A pointer to the newly created property on success, NULL on failure. |
3519 | * A pointer to the newly created property on success, NULL on failure. |
3474 | */ |
3520 | */ |
Line 3537... | Line 3583... | ||
3537 | */ |
3583 | */ |
3538 | if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) && |
3584 | if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) && |
3539 | (value > 63)) |
3585 | (value > 63)) |
3540 | return -EINVAL; |
3586 | return -EINVAL; |
Line 3541... | Line 3587... | ||
3541 | 3587 | ||
3542 | if (!list_empty(&property->enum_blob_list)) { |
3588 | if (!list_empty(&property->enum_list)) { |
3543 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { |
3589 | list_for_each_entry(prop_enum, &property->enum_list, head) { |
3544 | if (prop_enum->value == value) { |
3590 | if (prop_enum->value == value) { |
3545 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); |
3591 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); |
3546 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; |
3592 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; |
3547 | return 0; |
3593 | return 0; |
Line 3556... | Line 3602... | ||
3556 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); |
3602 | strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); |
3557 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; |
3603 | prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; |
3558 | prop_enum->value = value; |
3604 | prop_enum->value = value; |
Line 3559... | Line 3605... | ||
3559 | 3605 | ||
3560 | property->values[index] = value; |
3606 | property->values[index] = value; |
3561 | list_add_tail(&prop_enum->head, &property->enum_blob_list); |
3607 | list_add_tail(&prop_enum->head, &property->enum_list); |
3562 | return 0; |
3608 | return 0; |
3563 | } |
3609 | } |
Line 3564... | Line 3610... | ||
3564 | EXPORT_SYMBOL(drm_property_add_enum); |
3610 | EXPORT_SYMBOL(drm_property_add_enum); |
Line 3573... | Line 3619... | ||
3573 | */ |
3619 | */ |
3574 | void drm_property_destroy(struct drm_device *dev, struct drm_property *property) |
3620 | void drm_property_destroy(struct drm_device *dev, struct drm_property *property) |
3575 | { |
3621 | { |
3576 | struct drm_property_enum *prop_enum, *pt; |
3622 | struct drm_property_enum *prop_enum, *pt; |
Line 3577... | Line 3623... | ||
3577 | 3623 | ||
3578 | list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { |
3624 | list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) { |
3579 | list_del(&prop_enum->head); |
3625 | list_del(&prop_enum->head); |
3580 | kfree(prop_enum); |
3626 | kfree(prop_enum); |
Line 3581... | Line 3627... | ||
3581 | } |
3627 | } |
Line 3677... | Line 3723... | ||
3677 | } |
3723 | } |
3678 | EXPORT_SYMBOL(drm_object_property_get_value); |
3724 | EXPORT_SYMBOL(drm_object_property_get_value); |
Line 3679... | Line 3725... | ||
3679 | 3725 | ||
3680 | #if 0 |
3726 | #if 0 |
3681 | /** |
3727 | /** |
3682 | * drm_mode_getproperty_ioctl - get the current value of a connector's property |
3728 | * drm_mode_getproperty_ioctl - get the property metadata |
3683 | * @dev: DRM device |
3729 | * @dev: DRM device |
3684 | * @data: ioctl data |
3730 | * @data: ioctl data |
3685 | * @file_priv: DRM file info |
3731 | * @file_priv: DRM file info |
3686 | * |
3732 | * |
- | 3733 | * This function retrieves the metadata for a given property, like the different |
|
- | 3734 | * possible values for an enum property or the limits for a range property. |
|
- | 3735 | * |
|
3687 | * This function retrieves the current value for an connectors's property. |
3736 | * Blob properties are special |
3688 | * |
3737 | * |
3689 | * Called by the user via ioctl. |
3738 | * Called by the user via ioctl. |
3690 | * |
3739 | * |
3691 | * Returns: |
3740 | * Returns: |
3692 | * Zero on success, errno on failure. |
3741 | * Zero on success, negative errno on failure. |
3693 | */ |
3742 | */ |
3694 | int drm_mode_getproperty_ioctl(struct drm_device *dev, |
3743 | int drm_mode_getproperty_ioctl(struct drm_device *dev, |
3695 | void *data, struct drm_file *file_priv) |
3744 | void *data, struct drm_file *file_priv) |
3696 | { |
3745 | { |
3697 | struct drm_mode_get_property *out_resp = data; |
3746 | struct drm_mode_get_property *out_resp = data; |
3698 | struct drm_property *property; |
3747 | struct drm_property *property; |
3699 | int enum_count = 0; |
- | |
3700 | int blob_count = 0; |
3748 | int enum_count = 0; |
3701 | int value_count = 0; |
3749 | int value_count = 0; |
3702 | int ret = 0, i; |
3750 | int ret = 0, i; |
3703 | int copied; |
3751 | int copied; |
3704 | struct drm_property_enum *prop_enum; |
3752 | struct drm_property_enum *prop_enum; |
3705 | struct drm_mode_property_enum __user *enum_ptr; |
- | |
3706 | struct drm_property_blob *prop_blob; |
- | |
3707 | uint32_t __user *blob_id_ptr; |
3753 | struct drm_mode_property_enum __user *enum_ptr; |
3708 | uint64_t __user *values_ptr; |
- | |
Line 3709... | Line 3754... | ||
3709 | uint32_t __user *blob_length_ptr; |
3754 | uint64_t __user *values_ptr; |
3710 | 3755 | ||
Line 3711... | Line 3756... | ||
3711 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
3756 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
Line 3718... | Line 3763... | ||
3718 | goto done; |
3763 | goto done; |
3719 | } |
3764 | } |
Line 3720... | Line 3765... | ||
3720 | 3765 | ||
3721 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3766 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3722 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3767 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3723 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) |
3768 | list_for_each_entry(prop_enum, &property->enum_list, head) |
3724 | enum_count++; |
- | |
3725 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
- | |
3726 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) |
- | |
3727 | blob_count++; |
3769 | enum_count++; |
Line 3728... | Line 3770... | ||
3728 | } |
3770 | } |
Line 3729... | Line 3771... | ||
3729 | 3771 | ||
Line 3747... | Line 3789... | ||
3747 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3789 | if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) || |
3748 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3790 | drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
3749 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
3791 | if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { |
3750 | copied = 0; |
3792 | copied = 0; |
3751 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; |
3793 | enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; |
3752 | list_for_each_entry(prop_enum, &property->enum_blob_list, head) { |
3794 | list_for_each_entry(prop_enum, &property->enum_list, head) { |
Line 3753... | Line 3795... | ||
3753 | 3795 | ||
3754 | if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { |
3796 | if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { |
3755 | ret = -EFAULT; |
3797 | ret = -EFAULT; |
3756 | goto done; |
3798 | goto done; |
Line 3765... | Line 3807... | ||
3765 | } |
3807 | } |
3766 | } |
3808 | } |
3767 | out_resp->count_enum_blobs = enum_count; |
3809 | out_resp->count_enum_blobs = enum_count; |
3768 | } |
3810 | } |
Line 3769... | Line -... | ||
3769 | - | ||
- | 3811 | ||
3770 | if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
3812 | /* |
3771 | if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { |
- | |
3772 | copied = 0; |
3813 | * NOTE: The idea seems to have been to use this to read all the blob |
3773 | blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; |
3814 | * property values. But nothing ever added them to the corresponding |
3774 | blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; |
- | |
3775 | 3815 | * list, userspace always used the special-purpose get_blob ioctl to |
|
3776 | list_for_each_entry(prop_blob, &property->enum_blob_list, head) { |
3816 | * read the value for a blob property. It also doesn't make a lot of |
3777 | if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { |
- | |
3778 | ret = -EFAULT; |
3817 | * sense to return values here when everything else is just metadata for |
3779 | goto done; |
3818 | * the property itself. |
3780 | } |
- | |
3781 | 3819 | */ |
|
3782 | if (put_user(prop_blob->length, blob_length_ptr + copied)) { |
- | |
3783 | ret = -EFAULT; |
- | |
3784 | goto done; |
- | |
3785 | } |
- | |
3786 | - | ||
3787 | copied++; |
- | |
3788 | } |
- | |
3789 | } |
3820 | if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) |
3790 | out_resp->count_enum_blobs = blob_count; |
- | |
3791 | } |
3821 | out_resp->count_enum_blobs = 0; |
3792 | done: |
3822 | done: |
3793 | drm_modeset_unlock_all(dev); |
3823 | drm_modeset_unlock_all(dev); |
3794 | return ret; |
3824 | return ret; |
3795 | } |
3825 | } |
Line -... | Line 3826... | ||
- | 3826 | #endif |
|
3796 | #endif |
3827 | |
3797 | 3828 | static struct drm_property_blob * |
|
3798 | static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, |
3829 | drm_property_create_blob(struct drm_device *dev, size_t length, |
3799 | void *data) |
3830 | const void *data) |
3800 | { |
3831 | { |
Line 3801... | Line 3832... | ||
3801 | struct drm_property_blob *blob; |
3832 | struct drm_property_blob *blob; |
Line 3841... | Line 3872... | ||
3841 | * an object's blob property is just a normal modeset object id. |
3872 | * an object's blob property is just a normal modeset object id. |
3842 | * |
3873 | * |
3843 | * Called by the user via ioctl. |
3874 | * Called by the user via ioctl. |
3844 | * |
3875 | * |
3845 | * Returns: |
3876 | * Returns: |
3846 | * Zero on success, errno on failure. |
3877 | * Zero on success, negative errno on failure. |
3847 | */ |
3878 | */ |
3848 | int drm_mode_getblob_ioctl(struct drm_device *dev, |
3879 | int drm_mode_getblob_ioctl(struct drm_device *dev, |
3849 | void *data, struct drm_file *file_priv) |
3880 | void *data, struct drm_file *file_priv) |
3850 | { |
3881 | { |
3851 | struct drm_mode_get_blob *out_resp = data; |
3882 | struct drm_mode_get_blob *out_resp = data; |
Line 3876... | Line 3907... | ||
3876 | drm_modeset_unlock_all(dev); |
3907 | drm_modeset_unlock_all(dev); |
3877 | return ret; |
3908 | return ret; |
3878 | } |
3909 | } |
3879 | #endif |
3910 | #endif |
Line -... | Line 3911... | ||
- | 3911 | ||
- | 3912 | /** |
|
- | 3913 | * drm_mode_connector_set_path_property - set tile property on connector |
|
- | 3914 | * @connector: connector to set property on. |
|
- | 3915 | * @path: path to use for property. |
|
- | 3916 | * |
|
- | 3917 | * This creates a property to expose to userspace to specify a |
|
- | 3918 | * connector path. This is mainly used for DisplayPort MST where |
|
- | 3919 | * connectors have a topology and we want to allow userspace to give |
|
- | 3920 | * them more meaningful names. |
|
- | 3921 | * |
|
- | 3922 | * Returns: |
|
- | 3923 | * Zero on success, negative errno on failure. |
|
3880 | 3924 | */ |
|
3881 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
3925 | int drm_mode_connector_set_path_property(struct drm_connector *connector, |
3882 | char *path) |
3926 | const char *path) |
3883 | { |
3927 | { |
3884 | struct drm_device *dev = connector->dev; |
- | |
3885 | int ret, size; |
3928 | struct drm_device *dev = connector->dev; |
- | 3929 | size_t size = strlen(path) + 1; |
|
Line 3886... | Line 3930... | ||
3886 | size = strlen(path) + 1; |
3930 | int ret; |
3887 | 3931 | ||
3888 | connector->path_blob_ptr = drm_property_create_blob(connector->dev, |
3932 | connector->path_blob_ptr = drm_property_create_blob(connector->dev, |
3889 | size, path); |
3933 | size, path); |
Line 3896... | Line 3940... | ||
3896 | return ret; |
3940 | return ret; |
3897 | } |
3941 | } |
3898 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); |
3942 | EXPORT_SYMBOL(drm_mode_connector_set_path_property); |
Line 3899... | Line 3943... | ||
3899 | 3943 | ||
- | 3944 | /** |
|
- | 3945 | * drm_mode_connector_set_tile_property - set tile property on connector |
|
- | 3946 | * @connector: connector to set property on. |
|
- | 3947 | * |
|
- | 3948 | * This looks up the tile information for a connector, and creates a |
|
- | 3949 | * property for userspace to parse if it exists. The property is of |
|
- | 3950 | * the form of 8 integers using ':' as a separator. |
|
- | 3951 | * |
|
- | 3952 | * Returns: |
|
- | 3953 | * Zero on success, errno on failure. |
|
- | 3954 | */ |
|
- | 3955 | int drm_mode_connector_set_tile_property(struct drm_connector *connector) |
|
- | 3956 | { |
|
- | 3957 | struct drm_device *dev = connector->dev; |
|
- | 3958 | int ret, size; |
|
- | 3959 | char tile[256]; |
|
- | 3960 | ||
- | 3961 | if (connector->tile_blob_ptr) |
|
- | 3962 | drm_property_destroy_blob(dev, connector->tile_blob_ptr); |
|
- | 3963 | ||
- | 3964 | if (!connector->has_tile) { |
|
- | 3965 | connector->tile_blob_ptr = NULL; |
|
- | 3966 | ret = drm_object_property_set_value(&connector->base, |
|
- | 3967 | dev->mode_config.tile_property, 0); |
|
- | 3968 | return ret; |
|
- | 3969 | } |
|
- | 3970 | ||
- | 3971 | snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d", |
|
- | 3972 | connector->tile_group->id, connector->tile_is_single_monitor, |
|
- | 3973 | connector->num_h_tile, connector->num_v_tile, |
|
- | 3974 | connector->tile_h_loc, connector->tile_v_loc, |
|
- | 3975 | connector->tile_h_size, connector->tile_v_size); |
|
- | 3976 | size = strlen(tile) + 1; |
|
- | 3977 | ||
- | 3978 | connector->tile_blob_ptr = drm_property_create_blob(connector->dev, |
|
- | 3979 | size, tile); |
|
- | 3980 | if (!connector->tile_blob_ptr) |
|
- | 3981 | return -EINVAL; |
|
- | 3982 | ||
- | 3983 | ret = drm_object_property_set_value(&connector->base, |
|
- | 3984 | dev->mode_config.tile_property, |
|
- | 3985 | connector->tile_blob_ptr->base.id); |
|
- | 3986 | return ret; |
|
- | 3987 | } |
|
- | 3988 | EXPORT_SYMBOL(drm_mode_connector_set_tile_property); |
|
- | 3989 | ||
3900 | /** |
3990 | /** |
3901 | * drm_mode_connector_update_edid_property - update the edid property of a connector |
3991 | * drm_mode_connector_update_edid_property - update the edid property of a connector |
3902 | * @connector: drm connector |
3992 | * @connector: drm connector |
3903 | * @edid: new value of the edid property |
3993 | * @edid: new value of the edid property |
3904 | * |
3994 | * |
Line 3907... | Line 3997... | ||
3907 | * |
3997 | * |
3908 | * Returns: |
3998 | * Returns: |
3909 | * Zero on success, errno on failure. |
3999 | * Zero on success, errno on failure. |
3910 | */ |
4000 | */ |
3911 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
4001 | int drm_mode_connector_update_edid_property(struct drm_connector *connector, |
3912 | struct edid *edid) |
4002 | const struct edid *edid) |
3913 | { |
4003 | { |
3914 | struct drm_device *dev = connector->dev; |
4004 | struct drm_device *dev = connector->dev; |
- | 4005 | size_t size; |
|
3915 | int ret, size; |
4006 | int ret; |
Line 3916... | Line 4007... | ||
3916 | 4007 | ||
3917 | /* ignore requests to set edid when overridden */ |
4008 | /* ignore requests to set edid when overridden */ |
3918 | if (connector->override_edid) |
4009 | if (connector->override_edid) |
Line 3940... | Line 4031... | ||
3940 | 4031 | ||
3941 | return ret; |
4032 | return ret; |
3942 | } |
4033 | } |
Line 3943... | Line 4034... | ||
3943 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
4034 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
Line 3944... | Line 4035... | ||
3944 | 4035 | ||
3945 | #if 0 |
4036 | |
3946 | 4037 | ||
3947 | static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, |
4038 | static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, |
Line 3978... | Line 4069... | ||
3978 | drm_object_property_set_value(obj, property, value); |
4069 | drm_object_property_set_value(obj, property, value); |
Line 3979... | Line 4070... | ||
3979 | 4070 | ||
3980 | return ret; |
4071 | return ret; |
Line -... | Line 4072... | ||
- | 4072 | } |
|
- | 4073 | ||
- | 4074 | /** |
|
- | 4075 | * drm_mode_plane_set_obj_prop - set the value of a property |
|
- | 4076 | * @plane: drm plane object to set property value for |
|
- | 4077 | * @property: property to set |
|
- | 4078 | * @value: value the property should be set to |
|
- | 4079 | * |
|
- | 4080 | * This functions sets a given property on a given plane object. This function |
|
- | 4081 | * calls the driver's ->set_property callback and changes the software state of |
|
- | 4082 | * the property if the callback succeeds. |
|
- | 4083 | * |
|
- | 4084 | * Returns: |
|
3981 | } |
4085 | * Zero on success, error code on failure. |
3982 | 4086 | */ |
|
3983 | static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, |
4087 | int drm_mode_plane_set_obj_prop(struct drm_plane *plane, |
3984 | struct drm_property *property, |
4088 | struct drm_property *property, |
3985 | uint64_t value) |
4089 | uint64_t value) |
3986 | { |
4090 | { |
Line 3987... | Line 4091... | ||
3987 | int ret = -EINVAL; |
4091 | int ret = -EINVAL; |
3988 | struct drm_plane *plane = obj_to_plane(obj); |
4092 | struct drm_mode_object *obj = &plane->base; |
3989 | 4093 | ||
3990 | if (plane->funcs->set_property) |
4094 | if (plane->funcs->set_property) |
Line 3991... | Line 4095... | ||
3991 | ret = plane->funcs->set_property(plane, property, value); |
4095 | ret = plane->funcs->set_property(plane, property, value); |
3992 | if (!ret) |
4096 | if (!ret) |
- | 4097 | drm_object_property_set_value(obj, property, value); |
|
Line -... | Line 4098... | ||
- | 4098 | ||
3993 | drm_object_property_set_value(obj, property, value); |
4099 | return ret; |
3994 | 4100 | } |
|
3995 | return ret; |
4101 | EXPORT_SYMBOL(drm_mode_plane_set_obj_prop); |
3996 | } |
4102 | |
3997 | 4103 | #if 0 |
|
3998 | /** |
4104 | /** |
3999 | * drm_mode_getproperty_ioctl - get the current value of a object's property |
4105 | * drm_mode_obj_get_properties_ioctl - get the current value of a object's property |
Line 4006... | Line 4112... | ||
4006 | * plane objects. |
4112 | * plane objects. |
4007 | * |
4113 | * |
4008 | * Called by the user via ioctl. |
4114 | * Called by the user via ioctl. |
4009 | * |
4115 | * |
4010 | * Returns: |
4116 | * Returns: |
4011 | * Zero on success, errno on failure. |
4117 | * Zero on success, negative errno on failure. |
4012 | */ |
4118 | */ |
4013 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, |
4119 | int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, |
4014 | struct drm_file *file_priv) |
4120 | struct drm_file *file_priv) |
4015 | { |
4121 | { |
4016 | struct drm_mode_obj_get_properties *arg = data; |
4122 | struct drm_mode_obj_get_properties *arg = data; |
Line 4078... | Line 4184... | ||
4078 | * crtc and plane objects. |
4184 | * crtc and plane objects. |
4079 | * |
4185 | * |
4080 | * Called by the user via ioctl. |
4186 | * Called by the user via ioctl. |
4081 | * |
4187 | * |
4082 | * Returns: |
4188 | * Returns: |
4083 | * Zero on success, errno on failure. |
4189 | * Zero on success, negative errno on failure. |
4084 | */ |
4190 | */ |
4085 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, |
4191 | int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, |
4086 | struct drm_file *file_priv) |
4192 | struct drm_file *file_priv) |
4087 | { |
4193 | { |
4088 | struct drm_mode_obj_set_property *arg = data; |
4194 | struct drm_mode_obj_set_property *arg = data; |
Line 4130... | Line 4236... | ||
4130 | break; |
4236 | break; |
4131 | case DRM_MODE_OBJECT_CRTC: |
4237 | case DRM_MODE_OBJECT_CRTC: |
4132 | ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); |
4238 | ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); |
4133 | break; |
4239 | break; |
4134 | case DRM_MODE_OBJECT_PLANE: |
4240 | case DRM_MODE_OBJECT_PLANE: |
4135 | ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value); |
4241 | ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj), |
- | 4242 | property, arg->value); |
|
4136 | break; |
4243 | break; |
4137 | } |
4244 | } |
Line 4138... | Line 4245... | ||
4138 | 4245 | ||
4139 | out: |
4246 | out: |
Line 4150... | Line 4257... | ||
4150 | * This function links up a connector to an encoder. Note that the routing |
4257 | * This function links up a connector to an encoder. Note that the routing |
4151 | * restrictions between encoders and crtcs are exposed to userspace through the |
4258 | * restrictions between encoders and crtcs are exposed to userspace through the |
4152 | * possible_clones and possible_crtcs bitmasks. |
4259 | * possible_clones and possible_crtcs bitmasks. |
4153 | * |
4260 | * |
4154 | * Returns: |
4261 | * Returns: |
4155 | * Zero on success, errno on failure. |
4262 | * Zero on success, negative errno on failure. |
4156 | */ |
4263 | */ |
4157 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, |
4264 | int drm_mode_connector_attach_encoder(struct drm_connector *connector, |
4158 | struct drm_encoder *encoder) |
4265 | struct drm_encoder *encoder) |
4159 | { |
4266 | { |
4160 | int i; |
4267 | int i; |
Line 4177... | Line 4284... | ||
4177 | * Drivers which support gamma tables should set this to the supported gamma |
4284 | * Drivers which support gamma tables should set this to the supported gamma |
4178 | * table size when initializing the CRTC. Currently the drm core only supports a |
4285 | * table size when initializing the CRTC. Currently the drm core only supports a |
4179 | * fixed gamma table size. |
4286 | * fixed gamma table size. |
4180 | * |
4287 | * |
4181 | * Returns: |
4288 | * Returns: |
4182 | * Zero on success, errno on failure. |
4289 | * Zero on success, negative errno on failure. |
4183 | */ |
4290 | */ |
4184 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
4291 | int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, |
4185 | int gamma_size) |
4292 | int gamma_size) |
4186 | { |
4293 | { |
4187 | crtc->gamma_size = gamma_size; |
4294 | crtc->gamma_size = gamma_size; |
Line 4207... | Line 4314... | ||
4207 | * inquire the required gamma table size through drm_mode_gamma_get_ioctl. |
4314 | * inquire the required gamma table size through drm_mode_gamma_get_ioctl. |
4208 | * |
4315 | * |
4209 | * Called by the user via ioctl. |
4316 | * Called by the user via ioctl. |
4210 | * |
4317 | * |
4211 | * Returns: |
4318 | * Returns: |
4212 | * Zero on success, errno on failure. |
4319 | * Zero on success, negative errno on failure. |
4213 | */ |
4320 | */ |
4214 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, |
4321 | int drm_mode_gamma_set_ioctl(struct drm_device *dev, |
4215 | void *data, struct drm_file *file_priv) |
4322 | void *data, struct drm_file *file_priv) |
4216 | { |
4323 | { |
4217 | struct drm_mode_crtc_lut *crtc_lut = data; |
4324 | struct drm_mode_crtc_lut *crtc_lut = data; |
Line 4279... | Line 4386... | ||
4279 | * allocated storage. |
4386 | * allocated storage. |
4280 | * |
4387 | * |
4281 | * Called by the user via ioctl. |
4388 | * Called by the user via ioctl. |
4282 | * |
4389 | * |
4283 | * Returns: |
4390 | * Returns: |
4284 | * Zero on success, errno on failure. |
4391 | * Zero on success, negative errno on failure. |
4285 | */ |
4392 | */ |
4286 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
4393 | int drm_mode_gamma_get_ioctl(struct drm_device *dev, |
4287 | void *data, struct drm_file *file_priv) |
4394 | void *data, struct drm_file *file_priv) |
4288 | { |
4395 | { |
4289 | struct drm_mode_crtc_lut *crtc_lut = data; |
4396 | struct drm_mode_crtc_lut *crtc_lut = data; |
Line 4343... | Line 4450... | ||
4343 | * reset hardware and software state. |
4450 | * reset hardware and software state. |
4344 | */ |
4451 | */ |
4345 | void drm_mode_config_reset(struct drm_device *dev) |
4452 | void drm_mode_config_reset(struct drm_device *dev) |
4346 | { |
4453 | { |
4347 | struct drm_crtc *crtc; |
4454 | struct drm_crtc *crtc; |
- | 4455 | struct drm_plane *plane; |
|
4348 | struct drm_encoder *encoder; |
4456 | struct drm_encoder *encoder; |
4349 | struct drm_connector *connector; |
4457 | struct drm_connector *connector; |
Line -... | Line 4458... | ||
- | 4458 | ||
- | 4459 | list_for_each_entry(plane, &dev->mode_config.plane_list, head) |
|
- | 4460 | if (plane->funcs->reset) |
|
- | 4461 | plane->funcs->reset(plane); |
|
4350 | 4462 | ||
4351 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
4463 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
4352 | if (crtc->funcs->reset) |
4464 | if (crtc->funcs->reset) |
Line 4353... | Line 4465... | ||
4353 | crtc->funcs->reset(crtc); |
4465 | crtc->funcs->reset(crtc); |
Line 4574... | Line 4686... | ||
4574 | } |
4686 | } |
4575 | } |
4687 | } |
4576 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); |
4688 | EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); |
Line 4577... | Line 4689... | ||
4577 | 4689 | ||
- | 4690 | /** |
|
- | 4691 | * drm_rotation_simplify() - Try to simplify the rotation |
|
- | 4692 | * @rotation: Rotation to be simplified |
|
- | 4693 | * @supported_rotations: Supported rotations |
|
- | 4694 | * |
|
- | 4695 | * Attempt to simplify the rotation to a form that is supported. |
|
- | 4696 | * Eg. if the hardware supports everything except DRM_REFLECT_X |
|
- | 4697 | * one could call this function like this: |
|
- | 4698 | * |
|
- | 4699 | * drm_rotation_simplify(rotation, BIT(DRM_ROTATE_0) | |
|
- | 4700 | * BIT(DRM_ROTATE_90) | BIT(DRM_ROTATE_180) | |
|
- | 4701 | * BIT(DRM_ROTATE_270) | BIT(DRM_REFLECT_Y)); |
|
- | 4702 | * |
|
- | 4703 | * to eliminate the DRM_ROTATE_X flag. Depending on what kind of |
|
- | 4704 | * transforms the hardware supports, this function may not |
|
- | 4705 | * be able to produce a supported transform, so the caller should |
|
- | 4706 | * check the result afterwards. |
|
- | 4707 | */ |
|
- | 4708 | unsigned int drm_rotation_simplify(unsigned int rotation, |
|
- | 4709 | unsigned int supported_rotations) |
|
- | 4710 | { |
|
- | 4711 | if (rotation & ~supported_rotations) { |
|
- | 4712 | rotation ^= BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y); |
|
- | 4713 | rotation = (rotation & ~0xf) | BIT((ffs(rotation & 0xf) + 1) % 4); |
|
- | 4714 | } |
|
- | 4715 | ||
- | 4716 | return rotation; |
|
- | 4717 | } |
|
- | 4718 | EXPORT_SYMBOL(drm_rotation_simplify); |
|
- | 4719 | ||
4578 | /** |
4720 | /** |
4579 | * drm_mode_config_init - initialize DRM mode_configuration structure |
4721 | * drm_mode_config_init - initialize DRM mode_configuration structure |
4580 | * @dev: DRM device |
4722 | * @dev: DRM device |
4581 | * |
4723 | * |
4582 | * Initialize @dev's mode_config structure, used for tracking the graphics |
4724 | * Initialize @dev's mode_config structure, used for tracking the graphics |
Line 4600... | Line 4742... | ||
4600 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
4742 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
4601 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
4743 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
4602 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
4744 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
4603 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
4745 | INIT_LIST_HEAD(&dev->mode_config.plane_list); |
4604 | idr_init(&dev->mode_config.crtc_idr); |
4746 | idr_init(&dev->mode_config.crtc_idr); |
- | 4747 | idr_init(&dev->mode_config.tile_idr); |
|
Line 4605... | Line 4748... | ||
4605 | 4748 | ||
4606 | drm_modeset_lock_all(dev); |
4749 | drm_modeset_lock_all(dev); |
4607 | drm_mode_create_standard_connector_properties(dev); |
4750 | drm_mode_create_standard_connector_properties(dev); |
4608 | drm_mode_create_standard_plane_properties(dev); |
4751 | drm_mode_create_standard_plane_properties(dev); |
Line 4629... | Line 4772... | ||
4629 | * teardown time, no locking is required. It's the driver's job to ensure that |
4772 | * teardown time, no locking is required. It's the driver's job to ensure that |
4630 | * this guarantee actually holds true. |
4773 | * this guarantee actually holds true. |
4631 | * |
4774 | * |
4632 | * FIXME: cleanup any dangling user buffer objects too |
4775 | * FIXME: cleanup any dangling user buffer objects too |
4633 | */>>>>>>><>>>>=>=>>>>><>><>>>>>>>>>>><>><>>>>> |
4776 | */ |
- | 4777 | void drm_mode_config_cleanup(struct drm_device *dev) |
|
- | 4778 | { |
|
- | 4779 | struct drm_connector *connector, *ot; |
|
- | 4780 | struct drm_crtc *crtc, *ct; |
|
- | 4781 | struct drm_encoder *encoder, *enct; |
|
- | 4782 | struct drm_bridge *bridge, *brt; |
|
- | 4783 | struct drm_framebuffer *fb, *fbt; |
|
- | 4784 | struct drm_property *property, *pt; |
|
- | 4785 | struct drm_property_blob *blob, *bt; |
|
- | 4786 | struct drm_plane *plane, *plt; |
|
- | 4787 | ||
- | 4788 | list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, |
|
- | 4789 | head) { |
|
- | 4790 | encoder->funcs->destroy(encoder); |
|
- | 4791 | } |
|
- | 4792 | ||
- | 4793 | list_for_each_entry_safe(bridge, brt, |
|
- | 4794 | &dev->mode_config.bridge_list, head) { |
|
- | 4795 | bridge->funcs->destroy(bridge); |
|
- | 4796 | } |
|
- | 4797 | ||
- | 4798 | list_for_each_entry_safe(connector, ot, |
|
- | 4799 | &dev->mode_config.connector_list, head) { |
|
- | 4800 | connector->funcs->destroy(connector); |
|
- | 4801 | } |
|
- | 4802 | ||
- | 4803 | list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, |
|
- | 4804 | head) { |
|
- | 4805 | drm_property_destroy(dev, property); |
|
- | 4806 | } |
|
- | 4807 | ||
- | 4808 | list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, |
|
- | 4809 | head) { |
|
- | 4810 | drm_property_destroy_blob(dev, blob); |
|
- | 4811 | } |
|
- | 4812 | ||
- | 4813 | /* |
|
- | 4814 | * Single-threaded teardown context, so it's not required to grab the |
|
- | 4815 | * fb_lock to protect against concurrent fb_list access. Contrary, it |
|
- | 4816 | * would actually deadlock with the drm_framebuffer_cleanup function. |
|
- | 4817 | * |
|
- | 4818 | * Also, if there are any framebuffers left, that's a driver leak now, |
|
- | 4819 | * so politely WARN about this. |
|
- | 4820 | */ |
|
- | 4821 | WARN_ON(!list_empty(&dev->mode_config.fb_list)); |
|
- | 4822 | list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { |
|
- | 4823 | drm_framebuffer_remove(fb); |
|
- | 4824 | } |
|
- | 4825 | ||
- | 4826 | list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, |
|
- | 4827 | head) { |
|
- | 4828 | plane->funcs->destroy(plane); |
|
- | 4829 | } |
|
- | 4830 | ||
- | 4831 | list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { |
|
- | 4832 | crtc->funcs->destroy(crtc); |
|
- | 4833 | } |
|
- | 4834 | ||
- | 4835 | idr_destroy(&dev->mode_config.tile_idr); |
|
- | 4836 | idr_destroy(&dev->mode_config.crtc_idr); |
|
- | 4837 | drm_modeset_lock_fini(&dev->mode_config.connection_mutex); |
|
- | 4838 | } |
|
- | 4839 | EXPORT_SYMBOL(drm_mode_config_cleanup); |
|
- | 4840 | ||
- | 4841 | struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev, |
|
- | 4842 | unsigned int supported_rotations) |
|
- | 4843 | { |
|
- | 4844 | static const struct drm_prop_enum_list props[] = { |
|
- | 4845 | { DRM_ROTATE_0, "rotate-0" }, |
|
- | 4846 | { DRM_ROTATE_90, "rotate-90" }, |
|
- | 4847 | { DRM_ROTATE_180, "rotate-180" }, |
|
- | 4848 | { DRM_ROTATE_270, "rotate-270" }, |
|
- | 4849 | { DRM_REFLECT_X, "reflect-x" }, |
|
- | 4850 | { DRM_REFLECT_Y, "reflect-y" }, |
|
- | 4851 | }; |
|
- | 4852 | ||
- | 4853 | return drm_property_create_bitmask(dev, 0, "rotation", |
|
- | 4854 | props, ARRAY_SIZE(props), |
|
- | 4855 | supported_rotations); |
|
- | 4856 | } |
|
- | 4857 | EXPORT_SYMBOL(drm_mode_create_rotation_property); |
|
- | 4858 | ||
- | 4859 | /** |
|
- | 4860 | * DOC: Tile group |
|
- | 4861 | * |
|
- | 4862 | * Tile groups are used to represent tiled monitors with a unique |
|
- | 4863 | * integer identifier. Tiled monitors using DisplayID v1.3 have |
|
- | 4864 | * a unique 8-byte handle, we store this in a tile group, so we |
|
- | 4865 | * have a common identifier for all tiles in a monitor group. |
|
- | 4866 | */ |
|
- | 4867 | static void drm_tile_group_free(struct kref *kref) |
|
- | 4868 | { |
|
- | 4869 | struct drm_tile_group *tg = container_of(kref, struct drm_tile_group, refcount); |
|
- | 4870 | struct drm_device *dev = tg->dev; |
|
- | 4871 | mutex_lock(&dev->mode_config.idr_mutex); |
|
- | 4872 | idr_remove(&dev->mode_config.tile_idr, tg->id); |
|
- | 4873 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
- | 4874 | kfree(tg); |
|
- | 4875 | } |
|
- | 4876 | ||
- | 4877 | /** |
|
- | 4878 | * drm_mode_put_tile_group - drop a reference to a tile group. |
|
- | 4879 | * @dev: DRM device |
|
- | 4880 | * @tg: tile group to drop reference to. |
|
- | 4881 | * |
|
- | 4882 | * drop reference to tile group and free if 0. |
|
- | 4883 | */ |
|
- | 4884 | void drm_mode_put_tile_group(struct drm_device *dev, |
|
- | 4885 | struct drm_tile_group *tg) |
|
- | 4886 | { |
|
- | 4887 | kref_put(&tg->refcount, drm_tile_group_free); |
|
- | 4888 | } |
|
- | 4889 | ||
- | 4890 | /** |
|
- | 4891 | * drm_mode_get_tile_group - get a reference to an existing tile group |
|
- | 4892 | * @dev: DRM device |
|
- | 4893 | * @topology: 8-bytes unique per monitor. |
|
- | 4894 | * |
|
- | 4895 | * Use the unique bytes to get a reference to an existing tile group. |
|
- | 4896 | * |
|
- | 4897 | * RETURNS: |
|
- | 4898 | * tile group or NULL if not found. |
|
- | 4899 | */ |
|
- | 4900 | struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev, |
|
- | 4901 | char topology[8]) |
|
- | 4902 | { |
|
- | 4903 | struct drm_tile_group *tg; |
|
- | 4904 | int id; |
|
- | 4905 | mutex_lock(&dev->mode_config.idr_mutex); |
|
- | 4906 | idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) { |
|
- | 4907 | if (!memcmp(tg->group_data, topology, 8)) { |
|
- | 4908 | // if (!kref_get_unless_zero(&tg->refcount)) |
|
- | 4909 | // tg = NULL; |
|
- | 4910 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
- | 4911 | return tg; |
|
- | 4912 | } |
|
- | 4913 | } |
|
- | 4914 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
- | 4915 | return NULL; |
|
- | 4916 | } |
|
- | 4917 | ||
- | 4918 | /** |
|
- | 4919 | * drm_mode_create_tile_group - create a tile group from a displayid description |
|
- | 4920 | * @dev: DRM device |
|
- | 4921 | * @topology: 8-bytes unique per monitor. |
|
- | 4922 | * |
|
- | 4923 | * Create a tile group for the unique monitor, and get a unique |
|
- | 4924 | * identifier for the tile group. |
|
- | 4925 | * |
|
- | 4926 | * RETURNS: |
|
- | 4927 | * new tile group or error. |
|
- | 4928 | */ |
|
- | 4929 | struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev, |
|
- | 4930 | char topology[8]) |
|
- | 4931 | { |
|
- | 4932 | struct drm_tile_group *tg; |
|
- | 4933 | int ret; |
|
- | 4934 | ||
- | 4935 | tg = kzalloc(sizeof(*tg), GFP_KERNEL); |
|
- | 4936 | if (!tg) |
|
- | 4937 | return ERR_PTR(-ENOMEM); |
|
- | 4938 | ||
- | 4939 | kref_init(&tg->refcount); |
|
- | 4940 | memcpy(tg->group_data, topology, 8); |
|
- | 4941 | tg->dev = dev; |
|
- | 4942 | ||
- | 4943 | mutex_lock(&dev->mode_config.idr_mutex); |
|
- | 4944 | ret = idr_alloc(&dev->mode_config.tile_idr, tg, 1, 0, GFP_KERNEL); |
|
- | 4945 | if (ret >= 0) { |
|
- | 4946 | tg->id = ret; |
|
- | 4947 | } else { |
|
- | 4948 | kfree(tg); |
|
- | 4949 | tg = ERR_PTR(ret); |
|
- | 4950 | } |
|
- | 4951 | ||
- | 4952 | mutex_unlock(&dev->mode_config.idr_mutex); |
|
- | 4953 | return tg; |
|
- | 4954 | }>>>>>>><>>>>=>=>>>>><>><>>>>>>>>>>><>><>>>>> |