diff options
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 650 |
1 files changed, 406 insertions, 244 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 5213da499d39..6b6b07ff720b 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <drm/drm_edid.h> | 38 | #include <drm/drm_edid.h> |
39 | #include <drm/drm_fourcc.h> | 39 | #include <drm/drm_fourcc.h> |
40 | #include <drm/drm_modeset_lock.h> | 40 | #include <drm/drm_modeset_lock.h> |
41 | #include <drm/drm_atomic.h> | ||
41 | 42 | ||
42 | #include "drm_crtc_internal.h" | 43 | #include "drm_crtc_internal.h" |
43 | #include "drm_internal.h" | 44 | #include "drm_internal.h" |
@@ -61,8 +62,8 @@ static struct drm_framebuffer *add_framebuffer_internal(struct drm_device *dev, | |||
61 | /* | 62 | /* |
62 | * Global properties | 63 | * Global properties |
63 | */ | 64 | */ |
64 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = | 65 | static const struct drm_prop_enum_list drm_dpms_enum_list[] = { |
65 | { { DRM_MODE_DPMS_ON, "On" }, | 66 | { DRM_MODE_DPMS_ON, "On" }, |
66 | { DRM_MODE_DPMS_STANDBY, "Standby" }, | 67 | { DRM_MODE_DPMS_STANDBY, "Standby" }, |
67 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, | 68 | { DRM_MODE_DPMS_SUSPEND, "Suspend" }, |
68 | { DRM_MODE_DPMS_OFF, "Off" } | 69 | { DRM_MODE_DPMS_OFF, "Off" } |
@@ -70,8 +71,7 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = | |||
70 | 71 | ||
71 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) | 72 | DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) |
72 | 73 | ||
73 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = | 74 | static const struct drm_prop_enum_list drm_plane_type_enum_list[] = { |
74 | { | ||
75 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, | 75 | { DRM_PLANE_TYPE_OVERLAY, "Overlay" }, |
76 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, | 76 | { DRM_PLANE_TYPE_PRIMARY, "Primary" }, |
77 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, | 77 | { DRM_PLANE_TYPE_CURSOR, "Cursor" }, |
@@ -80,8 +80,7 @@ static const struct drm_prop_enum_list drm_plane_type_enum_list[] = | |||
80 | /* | 80 | /* |
81 | * Optional properties | 81 | * Optional properties |
82 | */ | 82 | */ |
83 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = | 83 | static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = { |
84 | { | ||
85 | { DRM_MODE_SCALE_NONE, "None" }, | 84 | { DRM_MODE_SCALE_NONE, "None" }, |
86 | { DRM_MODE_SCALE_FULLSCREEN, "Full" }, | 85 | { DRM_MODE_SCALE_FULLSCREEN, "Full" }, |
87 | { DRM_MODE_SCALE_CENTER, "Center" }, | 86 | { DRM_MODE_SCALE_CENTER, "Center" }, |
@@ -97,8 +96,7 @@ static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = { | |||
97 | /* | 96 | /* |
98 | * Non-global properties, but "required" for certain connectors. | 97 | * Non-global properties, but "required" for certain connectors. |
99 | */ | 98 | */ |
100 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = | 99 | static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = { |
101 | { | ||
102 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | 100 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
103 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | 101 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
104 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | 102 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
@@ -106,8 +104,7 @@ static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = | |||
106 | 104 | ||
107 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) | 105 | DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) |
108 | 106 | ||
109 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = | 107 | static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { |
110 | { | ||
111 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | 108 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
112 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ | 109 | { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ |
113 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ | 110 | { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ |
@@ -116,8 +113,7 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = | |||
116 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, | 113 | DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, |
117 | drm_dvi_i_subconnector_enum_list) | 114 | drm_dvi_i_subconnector_enum_list) |
118 | 115 | ||
119 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = | 116 | static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { |
120 | { | ||
121 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ | 117 | { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ |
122 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | 118 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
123 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | 119 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
@@ -127,8 +123,7 @@ static const struct drm_prop_enum_list drm_tv_select_enum_list[] = | |||
127 | 123 | ||
128 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) | 124 | DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) |
129 | 125 | ||
130 | static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = | 126 | static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = { |
131 | { | ||
132 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ | 127 | { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ |
133 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ | 128 | { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ |
134 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ | 129 | { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ |
@@ -154,8 +149,8 @@ struct drm_conn_prop_enum_list { | |||
154 | /* | 149 | /* |
155 | * Connector and encoder types. | 150 | * Connector and encoder types. |
156 | */ | 151 | */ |
157 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = | 152 | static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { |
158 | { { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, | 153 | { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, |
159 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, | 154 | { DRM_MODE_CONNECTOR_VGA, "VGA" }, |
160 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, | 155 | { DRM_MODE_CONNECTOR_DVII, "DVI-I" }, |
161 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, | 156 | { DRM_MODE_CONNECTOR_DVID, "DVI-D" }, |
@@ -174,8 +169,8 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = | |||
174 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, | 169 | { DRM_MODE_CONNECTOR_DSI, "DSI" }, |
175 | }; | 170 | }; |
176 | 171 | ||
177 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = | 172 | static const struct drm_prop_enum_list drm_encoder_enum_list[] = { |
178 | { { DRM_MODE_ENCODER_NONE, "None" }, | 173 | { DRM_MODE_ENCODER_NONE, "None" }, |
179 | { DRM_MODE_ENCODER_DAC, "DAC" }, | 174 | { DRM_MODE_ENCODER_DAC, "DAC" }, |
180 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, | 175 | { DRM_MODE_ENCODER_TMDS, "TMDS" }, |
181 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, | 176 | { DRM_MODE_ENCODER_LVDS, "LVDS" }, |
@@ -185,8 +180,7 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = | |||
185 | { DRM_MODE_ENCODER_DPMST, "DP MST" }, | 180 | { DRM_MODE_ENCODER_DPMST, "DP MST" }, |
186 | }; | 181 | }; |
187 | 182 | ||
188 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = | 183 | static const struct drm_prop_enum_list drm_subpixel_enum_list[] = { |
189 | { | ||
190 | { SubPixelUnknown, "Unknown" }, | 184 | { SubPixelUnknown, "Unknown" }, |
191 | { SubPixelHorizontalRGB, "Horizontal RGB" }, | 185 | { SubPixelHorizontalRGB, "Horizontal RGB" }, |
192 | { SubPixelHorizontalBGR, "Horizontal BGR" }, | 186 | { SubPixelHorizontalBGR, "Horizontal BGR" }, |
@@ -697,6 +691,10 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc, | |||
697 | if (cursor) | 691 | if (cursor) |
698 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); | 692 | cursor->possible_crtcs = 1 << drm_crtc_index(crtc); |
699 | 693 | ||
694 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | ||
695 | drm_object_attach_property(&crtc->base, config->prop_active, 0); | ||
696 | } | ||
697 | |||
700 | return 0; | 698 | return 0; |
701 | } | 699 | } |
702 | EXPORT_SYMBOL(drm_crtc_init_with_planes); | 700 | EXPORT_SYMBOL(drm_crtc_init_with_planes); |
@@ -768,6 +766,40 @@ static void drm_mode_remove(struct drm_connector *connector, | |||
768 | } | 766 | } |
769 | 767 | ||
770 | /** | 768 | /** |
769 | * drm_display_info_set_bus_formats - set the supported bus formats | ||
770 | * @info: display info to store bus formats in | ||
771 | * @formats: array containing the supported bus formats | ||
772 | * @num_formats: the number of entries in the fmts array | ||
773 | * | ||
774 | * Store the supported bus formats in display info structure. | ||
775 | * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for | ||
776 | * a full list of available formats. | ||
777 | */ | ||
778 | int drm_display_info_set_bus_formats(struct drm_display_info *info, | ||
779 | const u32 *formats, | ||
780 | unsigned int num_formats) | ||
781 | { | ||
782 | u32 *fmts = NULL; | ||
783 | |||
784 | if (!formats && num_formats) | ||
785 | return -EINVAL; | ||
786 | |||
787 | if (formats && num_formats) { | ||
788 | fmts = kmemdup(formats, sizeof(*formats) * num_formats, | ||
789 | GFP_KERNEL); | ||
790 | if (!fmts) | ||
791 | return -ENOMEM; | ||
792 | } | ||
793 | |||
794 | kfree(info->bus_formats); | ||
795 | info->bus_formats = fmts; | ||
796 | info->num_bus_formats = num_formats; | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | EXPORT_SYMBOL(drm_display_info_set_bus_formats); | ||
801 | |||
802 | /** | ||
771 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode | 803 | * drm_connector_get_cmdline_mode - reads the user's cmdline mode |
772 | * @connector: connector to quwery | 804 | * @connector: connector to quwery |
773 | * | 805 | * |
@@ -837,6 +869,7 @@ int drm_connector_init(struct drm_device *dev, | |||
837 | const struct drm_connector_funcs *funcs, | 869 | const struct drm_connector_funcs *funcs, |
838 | int connector_type) | 870 | int connector_type) |
839 | { | 871 | { |
872 | struct drm_mode_config *config = &dev->mode_config; | ||
840 | int ret; | 873 | int ret; |
841 | struct ida *connector_ida = | 874 | struct ida *connector_ida = |
842 | &drm_connector_enum_list[connector_type].ida; | 875 | &drm_connector_enum_list[connector_type].ida; |
@@ -875,16 +908,20 @@ int drm_connector_init(struct drm_device *dev, | |||
875 | 908 | ||
876 | /* We should add connectors at the end to avoid upsetting the connector | 909 | /* We should add connectors at the end to avoid upsetting the connector |
877 | * index too much. */ | 910 | * index too much. */ |
878 | list_add_tail(&connector->head, &dev->mode_config.connector_list); | 911 | list_add_tail(&connector->head, &config->connector_list); |
879 | dev->mode_config.num_connector++; | 912 | config->num_connector++; |
880 | 913 | ||
881 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) | 914 | if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) |
882 | drm_object_attach_property(&connector->base, | 915 | drm_object_attach_property(&connector->base, |
883 | dev->mode_config.edid_property, | 916 | config->edid_property, |
884 | 0); | 917 | 0); |
885 | 918 | ||
886 | drm_object_attach_property(&connector->base, | 919 | drm_object_attach_property(&connector->base, |
887 | dev->mode_config.dpms_property, 0); | 920 | config->dpms_property, 0); |
921 | |||
922 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | ||
923 | drm_object_attach_property(&connector->base, config->prop_crtc_id, 0); | ||
924 | } | ||
888 | 925 | ||
889 | connector->debugfs_entry = NULL; | 926 | connector->debugfs_entry = NULL; |
890 | 927 | ||
@@ -924,6 +961,7 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
924 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, | 961 | ida_remove(&drm_connector_enum_list[connector->connector_type].ida, |
925 | connector->connector_type_id); | 962 | connector->connector_type_id); |
926 | 963 | ||
964 | kfree(connector->display_info.bus_formats); | ||
927 | drm_mode_object_put(dev, &connector->base); | 965 | drm_mode_object_put(dev, &connector->base); |
928 | kfree(connector->name); | 966 | kfree(connector->name); |
929 | connector->name = NULL; | 967 | connector->name = NULL; |
@@ -1028,61 +1066,6 @@ void drm_connector_unplug_all(struct drm_device *dev) | |||
1028 | EXPORT_SYMBOL(drm_connector_unplug_all); | 1066 | EXPORT_SYMBOL(drm_connector_unplug_all); |
1029 | 1067 | ||
1030 | /** | 1068 | /** |
1031 | * drm_bridge_init - initialize a drm transcoder/bridge | ||
1032 | * @dev: drm device | ||
1033 | * @bridge: transcoder/bridge to set up | ||
1034 | * @funcs: bridge function table | ||
1035 | * | ||
1036 | * Initialises a preallocated bridge. Bridges should be | ||
1037 | * subclassed as part of driver connector objects. | ||
1038 | * | ||
1039 | * Returns: | ||
1040 | * Zero on success, error code on failure. | ||
1041 | */ | ||
1042 | int drm_bridge_init(struct drm_device *dev, struct drm_bridge *bridge, | ||
1043 | const struct drm_bridge_funcs *funcs) | ||
1044 | { | ||
1045 | int ret; | ||
1046 | |||
1047 | drm_modeset_lock_all(dev); | ||
1048 | |||
1049 | ret = drm_mode_object_get(dev, &bridge->base, DRM_MODE_OBJECT_BRIDGE); | ||
1050 | if (ret) | ||
1051 | goto out; | ||
1052 | |||
1053 | bridge->dev = dev; | ||
1054 | bridge->funcs = funcs; | ||
1055 | |||
1056 | list_add_tail(&bridge->head, &dev->mode_config.bridge_list); | ||
1057 | dev->mode_config.num_bridge++; | ||
1058 | |||
1059 | out: | ||
1060 | drm_modeset_unlock_all(dev); | ||
1061 | return ret; | ||
1062 | } | ||
1063 | EXPORT_SYMBOL(drm_bridge_init); | ||
1064 | |||
1065 | /** | ||
1066 | * drm_bridge_cleanup - cleans up an initialised bridge | ||
1067 | * @bridge: bridge to cleanup | ||
1068 | * | ||
1069 | * Cleans up the bridge but doesn't free the object. | ||
1070 | */ | ||
1071 | void drm_bridge_cleanup(struct drm_bridge *bridge) | ||
1072 | { | ||
1073 | struct drm_device *dev = bridge->dev; | ||
1074 | |||
1075 | drm_modeset_lock_all(dev); | ||
1076 | drm_mode_object_put(dev, &bridge->base); | ||
1077 | list_del(&bridge->head); | ||
1078 | dev->mode_config.num_bridge--; | ||
1079 | drm_modeset_unlock_all(dev); | ||
1080 | |||
1081 | memset(bridge, 0, sizeof(*bridge)); | ||
1082 | } | ||
1083 | EXPORT_SYMBOL(drm_bridge_cleanup); | ||
1084 | |||
1085 | /** | ||
1086 | * drm_encoder_init - Init a preallocated encoder | 1069 | * drm_encoder_init - Init a preallocated encoder |
1087 | * @dev: drm device | 1070 | * @dev: drm device |
1088 | * @encoder: the encoder to init | 1071 | * @encoder: the encoder to init |
@@ -1142,6 +1125,7 @@ EXPORT_SYMBOL(drm_encoder_init); | |||
1142 | void drm_encoder_cleanup(struct drm_encoder *encoder) | 1125 | void drm_encoder_cleanup(struct drm_encoder *encoder) |
1143 | { | 1126 | { |
1144 | struct drm_device *dev = encoder->dev; | 1127 | struct drm_device *dev = encoder->dev; |
1128 | |||
1145 | drm_modeset_lock_all(dev); | 1129 | drm_modeset_lock_all(dev); |
1146 | drm_mode_object_put(dev, &encoder->base); | 1130 | drm_mode_object_put(dev, &encoder->base); |
1147 | kfree(encoder->name); | 1131 | kfree(encoder->name); |
@@ -1174,6 +1158,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1174 | const uint32_t *formats, uint32_t format_count, | 1158 | const uint32_t *formats, uint32_t format_count, |
1175 | enum drm_plane_type type) | 1159 | enum drm_plane_type type) |
1176 | { | 1160 | { |
1161 | struct drm_mode_config *config = &dev->mode_config; | ||
1177 | int ret; | 1162 | int ret; |
1178 | 1163 | ||
1179 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); | 1164 | ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); |
@@ -1185,8 +1170,8 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1185 | plane->base.properties = &plane->properties; | 1170 | plane->base.properties = &plane->properties; |
1186 | plane->dev = dev; | 1171 | plane->dev = dev; |
1187 | plane->funcs = funcs; | 1172 | plane->funcs = funcs; |
1188 | plane->format_types = kmalloc(sizeof(uint32_t) * format_count, | 1173 | plane->format_types = kmalloc_array(format_count, sizeof(uint32_t), |
1189 | GFP_KERNEL); | 1174 | GFP_KERNEL); |
1190 | if (!plane->format_types) { | 1175 | if (!plane->format_types) { |
1191 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); | 1176 | DRM_DEBUG_KMS("out of memory when allocating plane\n"); |
1192 | drm_mode_object_put(dev, &plane->base); | 1177 | drm_mode_object_put(dev, &plane->base); |
@@ -1198,15 +1183,28 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, | |||
1198 | plane->possible_crtcs = possible_crtcs; | 1183 | plane->possible_crtcs = possible_crtcs; |
1199 | plane->type = type; | 1184 | plane->type = type; |
1200 | 1185 | ||
1201 | list_add_tail(&plane->head, &dev->mode_config.plane_list); | 1186 | list_add_tail(&plane->head, &config->plane_list); |
1202 | dev->mode_config.num_total_plane++; | 1187 | config->num_total_plane++; |
1203 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) | 1188 | if (plane->type == DRM_PLANE_TYPE_OVERLAY) |
1204 | dev->mode_config.num_overlay_plane++; | 1189 | config->num_overlay_plane++; |
1205 | 1190 | ||
1206 | drm_object_attach_property(&plane->base, | 1191 | drm_object_attach_property(&plane->base, |
1207 | dev->mode_config.plane_type_property, | 1192 | config->plane_type_property, |
1208 | plane->type); | 1193 | plane->type); |
1209 | 1194 | ||
1195 | if (drm_core_check_feature(dev, DRIVER_ATOMIC)) { | ||
1196 | drm_object_attach_property(&plane->base, config->prop_fb_id, 0); | ||
1197 | drm_object_attach_property(&plane->base, config->prop_crtc_id, 0); | ||
1198 | drm_object_attach_property(&plane->base, config->prop_crtc_x, 0); | ||
1199 | drm_object_attach_property(&plane->base, config->prop_crtc_y, 0); | ||
1200 | drm_object_attach_property(&plane->base, config->prop_crtc_w, 0); | ||
1201 | drm_object_attach_property(&plane->base, config->prop_crtc_h, 0); | ||
1202 | drm_object_attach_property(&plane->base, config->prop_src_x, 0); | ||
1203 | drm_object_attach_property(&plane->base, config->prop_src_y, 0); | ||
1204 | drm_object_attach_property(&plane->base, config->prop_src_w, 0); | ||
1205 | drm_object_attach_property(&plane->base, config->prop_src_h, 0); | ||
1206 | } | ||
1207 | |||
1210 | return 0; | 1208 | return 0; |
1211 | } | 1209 | } |
1212 | EXPORT_SYMBOL(drm_universal_plane_init); | 1210 | EXPORT_SYMBOL(drm_universal_plane_init); |
@@ -1328,50 +1326,115 @@ void drm_plane_force_disable(struct drm_plane *plane) | |||
1328 | } | 1326 | } |
1329 | EXPORT_SYMBOL(drm_plane_force_disable); | 1327 | EXPORT_SYMBOL(drm_plane_force_disable); |
1330 | 1328 | ||
1331 | static int drm_mode_create_standard_connector_properties(struct drm_device *dev) | 1329 | static int drm_mode_create_standard_properties(struct drm_device *dev) |
1332 | { | 1330 | { |
1333 | struct drm_property *edid; | 1331 | struct drm_property *prop; |
1334 | struct drm_property *dpms; | ||
1335 | struct drm_property *dev_path; | ||
1336 | 1332 | ||
1337 | /* | 1333 | /* |
1338 | * Standard properties (apply to all connectors) | 1334 | * Standard properties (apply to all connectors) |
1339 | */ | 1335 | */ |
1340 | edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | | 1336 | prop = drm_property_create(dev, DRM_MODE_PROP_BLOB | |
1341 | DRM_MODE_PROP_IMMUTABLE, | 1337 | DRM_MODE_PROP_IMMUTABLE, |
1342 | "EDID", 0); | 1338 | "EDID", 0); |
1343 | dev->mode_config.edid_property = edid; | 1339 | if (!prop) |
1340 | return -ENOMEM; | ||
1341 | dev->mode_config.edid_property = prop; | ||
1344 | 1342 | ||
1345 | dpms = drm_property_create_enum(dev, 0, | 1343 | prop = drm_property_create_enum(dev, 0, |
1346 | "DPMS", drm_dpms_enum_list, | 1344 | "DPMS", drm_dpms_enum_list, |
1347 | ARRAY_SIZE(drm_dpms_enum_list)); | 1345 | ARRAY_SIZE(drm_dpms_enum_list)); |
1348 | dev->mode_config.dpms_property = dpms; | 1346 | if (!prop) |
1349 | 1347 | return -ENOMEM; | |
1350 | dev_path = drm_property_create(dev, | 1348 | dev->mode_config.dpms_property = prop; |
1351 | DRM_MODE_PROP_BLOB | | ||
1352 | DRM_MODE_PROP_IMMUTABLE, | ||
1353 | "PATH", 0); | ||
1354 | dev->mode_config.path_property = dev_path; | ||
1355 | |||
1356 | dev->mode_config.tile_property = drm_property_create(dev, | ||
1357 | DRM_MODE_PROP_BLOB | | ||
1358 | DRM_MODE_PROP_IMMUTABLE, | ||
1359 | "TILE", 0); | ||
1360 | 1349 | ||
1361 | return 0; | 1350 | prop = drm_property_create(dev, |
1362 | } | 1351 | DRM_MODE_PROP_BLOB | |
1352 | DRM_MODE_PROP_IMMUTABLE, | ||
1353 | "PATH", 0); | ||
1354 | if (!prop) | ||
1355 | return -ENOMEM; | ||
1356 | dev->mode_config.path_property = prop; | ||
1363 | 1357 | ||
1364 | static int drm_mode_create_standard_plane_properties(struct drm_device *dev) | 1358 | prop = drm_property_create(dev, |
1365 | { | 1359 | DRM_MODE_PROP_BLOB | |
1366 | struct drm_property *type; | 1360 | DRM_MODE_PROP_IMMUTABLE, |
1361 | "TILE", 0); | ||
1362 | if (!prop) | ||
1363 | return -ENOMEM; | ||
1364 | dev->mode_config.tile_property = prop; | ||
1367 | 1365 | ||
1368 | /* | 1366 | prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, |
1369 | * Standard properties (apply to all planes) | ||
1370 | */ | ||
1371 | type = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, | ||
1372 | "type", drm_plane_type_enum_list, | 1367 | "type", drm_plane_type_enum_list, |
1373 | ARRAY_SIZE(drm_plane_type_enum_list)); | 1368 | ARRAY_SIZE(drm_plane_type_enum_list)); |
1374 | dev->mode_config.plane_type_property = type; | 1369 | if (!prop) |
1370 | return -ENOMEM; | ||
1371 | dev->mode_config.plane_type_property = prop; | ||
1372 | |||
1373 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1374 | "SRC_X", 0, UINT_MAX); | ||
1375 | if (!prop) | ||
1376 | return -ENOMEM; | ||
1377 | dev->mode_config.prop_src_x = prop; | ||
1378 | |||
1379 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1380 | "SRC_Y", 0, UINT_MAX); | ||
1381 | if (!prop) | ||
1382 | return -ENOMEM; | ||
1383 | dev->mode_config.prop_src_y = prop; | ||
1384 | |||
1385 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1386 | "SRC_W", 0, UINT_MAX); | ||
1387 | if (!prop) | ||
1388 | return -ENOMEM; | ||
1389 | dev->mode_config.prop_src_w = prop; | ||
1390 | |||
1391 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1392 | "SRC_H", 0, UINT_MAX); | ||
1393 | if (!prop) | ||
1394 | return -ENOMEM; | ||
1395 | dev->mode_config.prop_src_h = prop; | ||
1396 | |||
1397 | prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1398 | "CRTC_X", INT_MIN, INT_MAX); | ||
1399 | if (!prop) | ||
1400 | return -ENOMEM; | ||
1401 | dev->mode_config.prop_crtc_x = prop; | ||
1402 | |||
1403 | prop = drm_property_create_signed_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1404 | "CRTC_Y", INT_MIN, INT_MAX); | ||
1405 | if (!prop) | ||
1406 | return -ENOMEM; | ||
1407 | dev->mode_config.prop_crtc_y = prop; | ||
1408 | |||
1409 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1410 | "CRTC_W", 0, INT_MAX); | ||
1411 | if (!prop) | ||
1412 | return -ENOMEM; | ||
1413 | dev->mode_config.prop_crtc_w = prop; | ||
1414 | |||
1415 | prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC, | ||
1416 | "CRTC_H", 0, INT_MAX); | ||
1417 | if (!prop) | ||
1418 | return -ENOMEM; | ||
1419 | dev->mode_config.prop_crtc_h = prop; | ||
1420 | |||
1421 | prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, | ||
1422 | "FB_ID", DRM_MODE_OBJECT_FB); | ||
1423 | if (!prop) | ||
1424 | return -ENOMEM; | ||
1425 | dev->mode_config.prop_fb_id = prop; | ||
1426 | |||
1427 | prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC, | ||
1428 | "CRTC_ID", DRM_MODE_OBJECT_CRTC); | ||
1429 | if (!prop) | ||
1430 | return -ENOMEM; | ||
1431 | dev->mode_config.prop_crtc_id = prop; | ||
1432 | |||
1433 | prop = drm_property_create_bool(dev, DRM_MODE_PROP_ATOMIC, | ||
1434 | "ACTIVE"); | ||
1435 | if (!prop) | ||
1436 | return -ENOMEM; | ||
1437 | dev->mode_config.prop_active = prop; | ||
1375 | 1438 | ||
1376 | return 0; | 1439 | return 0; |
1377 | } | 1440 | } |
@@ -1597,16 +1660,14 @@ static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *gr | |||
1597 | total_objects += dev->mode_config.num_crtc; | 1660 | total_objects += dev->mode_config.num_crtc; |
1598 | total_objects += dev->mode_config.num_connector; | 1661 | total_objects += dev->mode_config.num_connector; |
1599 | total_objects += dev->mode_config.num_encoder; | 1662 | total_objects += dev->mode_config.num_encoder; |
1600 | total_objects += dev->mode_config.num_bridge; | ||
1601 | 1663 | ||
1602 | group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); | 1664 | group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL); |
1603 | if (!group->id_list) | 1665 | if (!group->id_list) |
1604 | return -ENOMEM; | 1666 | return -ENOMEM; |
1605 | 1667 | ||
1606 | group->num_crtcs = 0; | 1668 | group->num_crtcs = 0; |
1607 | group->num_connectors = 0; | 1669 | group->num_connectors = 0; |
1608 | group->num_encoders = 0; | 1670 | group->num_encoders = 0; |
1609 | group->num_bridges = 0; | ||
1610 | return 0; | 1671 | return 0; |
1611 | } | 1672 | } |
1612 | 1673 | ||
@@ -1626,10 +1687,10 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, | |||
1626 | struct drm_crtc *crtc; | 1687 | struct drm_crtc *crtc; |
1627 | struct drm_encoder *encoder; | 1688 | struct drm_encoder *encoder; |
1628 | struct drm_connector *connector; | 1689 | struct drm_connector *connector; |
1629 | struct drm_bridge *bridge; | ||
1630 | int ret; | 1690 | int ret; |
1631 | 1691 | ||
1632 | if ((ret = drm_mode_group_init(dev, group))) | 1692 | ret = drm_mode_group_init(dev, group); |
1693 | if (ret) | ||
1633 | return ret; | 1694 | return ret; |
1634 | 1695 | ||
1635 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 1696 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) |
@@ -1643,11 +1704,6 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, | |||
1643 | group->id_list[group->num_crtcs + group->num_encoders + | 1704 | group->id_list[group->num_crtcs + group->num_encoders + |
1644 | group->num_connectors++] = connector->base.id; | 1705 | group->num_connectors++] = connector->base.id; |
1645 | 1706 | ||
1646 | list_for_each_entry(bridge, &dev->mode_config.bridge_list, head) | ||
1647 | group->id_list[group->num_crtcs + group->num_encoders + | ||
1648 | group->num_connectors + group->num_bridges++] = | ||
1649 | bridge->base.id; | ||
1650 | |||
1651 | return 0; | 1707 | return 0; |
1652 | } | 1708 | } |
1653 | EXPORT_SYMBOL(drm_mode_group_init_legacy_group); | 1709 | EXPORT_SYMBOL(drm_mode_group_init_legacy_group); |
@@ -1996,6 +2052,44 @@ static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *conne | |||
1996 | return connector->encoder; | 2052 | return connector->encoder; |
1997 | } | 2053 | } |
1998 | 2054 | ||
2055 | /* helper for getconnector and getproperties ioctls */ | ||
2056 | static int get_properties(struct drm_mode_object *obj, bool atomic, | ||
2057 | uint32_t __user *prop_ptr, uint64_t __user *prop_values, | ||
2058 | uint32_t *arg_count_props) | ||
2059 | { | ||
2060 | int props_count; | ||
2061 | int i, ret, copied; | ||
2062 | |||
2063 | props_count = obj->properties->count; | ||
2064 | if (!atomic) | ||
2065 | props_count -= obj->properties->atomic_count; | ||
2066 | |||
2067 | if ((*arg_count_props >= props_count) && props_count) { | ||
2068 | for (i = 0, copied = 0; copied < props_count; i++) { | ||
2069 | struct drm_property *prop = obj->properties->properties[i]; | ||
2070 | uint64_t val; | ||
2071 | |||
2072 | if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic) | ||
2073 | continue; | ||
2074 | |||
2075 | ret = drm_object_property_get_value(obj, prop, &val); | ||
2076 | if (ret) | ||
2077 | return ret; | ||
2078 | |||
2079 | if (put_user(prop->base.id, prop_ptr + copied)) | ||
2080 | return -EFAULT; | ||
2081 | |||
2082 | if (put_user(val, prop_values + copied)) | ||
2083 | return -EFAULT; | ||
2084 | |||
2085 | copied++; | ||
2086 | } | ||
2087 | } | ||
2088 | *arg_count_props = props_count; | ||
2089 | |||
2090 | return 0; | ||
2091 | } | ||
2092 | |||
1999 | /** | 2093 | /** |
2000 | * drm_mode_getconnector - get connector configuration | 2094 | * drm_mode_getconnector - get connector configuration |
2001 | * @dev: drm device for the ioctl | 2095 | * @dev: drm device for the ioctl |
@@ -2017,15 +2111,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2017 | struct drm_encoder *encoder; | 2111 | struct drm_encoder *encoder; |
2018 | struct drm_display_mode *mode; | 2112 | struct drm_display_mode *mode; |
2019 | int mode_count = 0; | 2113 | int mode_count = 0; |
2020 | int props_count = 0; | ||
2021 | int encoders_count = 0; | 2114 | int encoders_count = 0; |
2022 | int ret = 0; | 2115 | int ret = 0; |
2023 | int copied = 0; | 2116 | int copied = 0; |
2024 | int i; | 2117 | int i; |
2025 | struct drm_mode_modeinfo u_mode; | 2118 | struct drm_mode_modeinfo u_mode; |
2026 | struct drm_mode_modeinfo __user *mode_ptr; | 2119 | struct drm_mode_modeinfo __user *mode_ptr; |
2027 | uint32_t __user *prop_ptr; | ||
2028 | uint64_t __user *prop_values; | ||
2029 | uint32_t __user *encoder_ptr; | 2120 | uint32_t __user *encoder_ptr; |
2030 | 2121 | ||
2031 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 2122 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
@@ -2043,13 +2134,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2043 | goto out; | 2134 | goto out; |
2044 | } | 2135 | } |
2045 | 2136 | ||
2046 | props_count = connector->properties.count; | 2137 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) |
2047 | 2138 | if (connector->encoder_ids[i] != 0) | |
2048 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
2049 | if (connector->encoder_ids[i] != 0) { | ||
2050 | encoders_count++; | 2139 | encoders_count++; |
2051 | } | ||
2052 | } | ||
2053 | 2140 | ||
2054 | if (out_resp->count_modes == 0) { | 2141 | if (out_resp->count_modes == 0) { |
2055 | connector->funcs->fill_modes(connector, | 2142 | connector->funcs->fill_modes(connector, |
@@ -2069,14 +2156,13 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2069 | out_resp->mm_height = connector->display_info.height_mm; | 2156 | out_resp->mm_height = connector->display_info.height_mm; |
2070 | out_resp->subpixel = connector->display_info.subpixel_order; | 2157 | out_resp->subpixel = connector->display_info.subpixel_order; |
2071 | out_resp->connection = connector->status; | 2158 | out_resp->connection = connector->status; |
2072 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
2073 | 2159 | ||
2160 | drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); | ||
2074 | encoder = drm_connector_get_encoder(connector); | 2161 | encoder = drm_connector_get_encoder(connector); |
2075 | if (encoder) | 2162 | if (encoder) |
2076 | out_resp->encoder_id = encoder->base.id; | 2163 | out_resp->encoder_id = encoder->base.id; |
2077 | else | 2164 | else |
2078 | out_resp->encoder_id = 0; | 2165 | out_resp->encoder_id = 0; |
2079 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
2080 | 2166 | ||
2081 | /* | 2167 | /* |
2082 | * This ioctl is called twice, once to determine how much space is | 2168 | * This ioctl is called twice, once to determine how much space is |
@@ -2100,26 +2186,12 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2100 | } | 2186 | } |
2101 | out_resp->count_modes = mode_count; | 2187 | out_resp->count_modes = mode_count; |
2102 | 2188 | ||
2103 | if ((out_resp->count_props >= props_count) && props_count) { | 2189 | ret = get_properties(&connector->base, file_priv->atomic, |
2104 | copied = 0; | 2190 | (uint32_t __user *)(unsigned long)(out_resp->props_ptr), |
2105 | prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); | 2191 | (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr), |
2106 | prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); | 2192 | &out_resp->count_props); |
2107 | for (i = 0; i < connector->properties.count; i++) { | 2193 | if (ret) |
2108 | if (put_user(connector->properties.ids[i], | 2194 | goto out; |
2109 | prop_ptr + copied)) { | ||
2110 | ret = -EFAULT; | ||
2111 | goto out; | ||
2112 | } | ||
2113 | |||
2114 | if (put_user(connector->properties.values[i], | ||
2115 | prop_values + copied)) { | ||
2116 | ret = -EFAULT; | ||
2117 | goto out; | ||
2118 | } | ||
2119 | copied++; | ||
2120 | } | ||
2121 | } | ||
2122 | out_resp->count_props = props_count; | ||
2123 | 2195 | ||
2124 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { | 2196 | if ((out_resp->count_encoders >= encoders_count) && encoders_count) { |
2125 | copied = 0; | 2197 | copied = 0; |
@@ -2138,6 +2210,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, | |||
2138 | out_resp->count_encoders = encoders_count; | 2210 | out_resp->count_encoders = encoders_count; |
2139 | 2211 | ||
2140 | out: | 2212 | out: |
2213 | drm_modeset_unlock(&dev->mode_config.connection_mutex); | ||
2141 | mutex_unlock(&dev->mode_config.mutex); | 2214 | mutex_unlock(&dev->mode_config.mutex); |
2142 | 2215 | ||
2143 | return ret; | 2216 | return ret; |
@@ -2529,7 +2602,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, | |||
2529 | * | 2602 | * |
2530 | * This is a little helper to wrap internal calls to the ->set_config driver | 2603 | * This is a little helper to wrap internal calls to the ->set_config driver |
2531 | * interface. The only thing it adds is correct refcounting dance. | 2604 | * interface. The only thing it adds is correct refcounting dance. |
2532 | * | 2605 | * |
2533 | * Returns: | 2606 | * Returns: |
2534 | * Zero on success, negative errno on failure. | 2607 | * Zero on success, negative errno on failure. |
2535 | */ | 2608 | */ |
@@ -2569,6 +2642,27 @@ int drm_mode_set_config_internal(struct drm_mode_set *set) | |||
2569 | EXPORT_SYMBOL(drm_mode_set_config_internal); | 2642 | EXPORT_SYMBOL(drm_mode_set_config_internal); |
2570 | 2643 | ||
2571 | /** | 2644 | /** |
2645 | * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode | ||
2646 | * @mode: mode to query | ||
2647 | * @hdisplay: hdisplay value to fill in | ||
2648 | * @vdisplay: vdisplay value to fill in | ||
2649 | * | ||
2650 | * The vdisplay value will be doubled if the specified mode is a stereo mode of | ||
2651 | * the appropriate layout. | ||
2652 | */ | ||
2653 | void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, | ||
2654 | int *hdisplay, int *vdisplay) | ||
2655 | { | ||
2656 | struct drm_display_mode adjusted; | ||
2657 | |||
2658 | drm_mode_copy(&adjusted, mode); | ||
2659 | drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY); | ||
2660 | *hdisplay = adjusted.crtc_hdisplay; | ||
2661 | *vdisplay = adjusted.crtc_vdisplay; | ||
2662 | } | ||
2663 | EXPORT_SYMBOL(drm_crtc_get_hv_timing); | ||
2664 | |||
2665 | /** | ||
2572 | * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the | 2666 | * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the |
2573 | * CRTC viewport | 2667 | * CRTC viewport |
2574 | * @crtc: CRTC that framebuffer will be displayed on | 2668 | * @crtc: CRTC that framebuffer will be displayed on |
@@ -2585,16 +2679,7 @@ int drm_crtc_check_viewport(const struct drm_crtc *crtc, | |||
2585 | { | 2679 | { |
2586 | int hdisplay, vdisplay; | 2680 | int hdisplay, vdisplay; |
2587 | 2681 | ||
2588 | hdisplay = mode->hdisplay; | 2682 | drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay); |
2589 | vdisplay = mode->vdisplay; | ||
2590 | |||
2591 | if (drm_mode_is_stereo(mode)) { | ||
2592 | struct drm_display_mode adjusted = *mode; | ||
2593 | |||
2594 | drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE); | ||
2595 | hdisplay = adjusted.crtc_hdisplay; | ||
2596 | vdisplay = adjusted.crtc_vdisplay; | ||
2597 | } | ||
2598 | 2683 | ||
2599 | if (crtc->invert_dimensions) | 2684 | if (crtc->invert_dimensions) |
2600 | swap(hdisplay, vdisplay); | 2685 | swap(hdisplay, vdisplay); |
@@ -2690,6 +2775,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2690 | goto out; | 2775 | goto out; |
2691 | } | 2776 | } |
2692 | 2777 | ||
2778 | mode->status = drm_mode_validate_basic(mode); | ||
2779 | if (mode->status != MODE_OK) { | ||
2780 | ret = -EINVAL; | ||
2781 | goto out; | ||
2782 | } | ||
2783 | |||
2693 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); | 2784 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
2694 | 2785 | ||
2695 | ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, | 2786 | ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y, |
@@ -2721,9 +2812,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
2721 | goto out; | 2812 | goto out; |
2722 | } | 2813 | } |
2723 | 2814 | ||
2724 | connector_set = kmalloc(crtc_req->count_connectors * | 2815 | connector_set = kmalloc_array(crtc_req->count_connectors, |
2725 | sizeof(struct drm_connector *), | 2816 | sizeof(struct drm_connector *), |
2726 | GFP_KERNEL); | 2817 | GFP_KERNEL); |
2727 | if (!connector_set) { | 2818 | if (!connector_set) { |
2728 | ret = -ENOMEM; | 2819 | ret = -ENOMEM; |
2729 | goto out; | 2820 | goto out; |
@@ -2968,6 +3059,7 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev, | |||
2968 | void *data, struct drm_file *file_priv) | 3059 | void *data, struct drm_file *file_priv) |
2969 | { | 3060 | { |
2970 | struct drm_mode_cursor2 *req = data; | 3061 | struct drm_mode_cursor2 *req = data; |
3062 | |||
2971 | return drm_mode_cursor_common(dev, req, file_priv); | 3063 | return drm_mode_cursor_common(dev, req, file_priv); |
2972 | } | 3064 | } |
2973 | 3065 | ||
@@ -3415,7 +3507,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, | |||
3415 | ret = -EINVAL; | 3507 | ret = -EINVAL; |
3416 | goto out_err1; | 3508 | goto out_err1; |
3417 | } | 3509 | } |
3418 | clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); | 3510 | clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); |
3419 | if (!clips) { | 3511 | if (!clips) { |
3420 | ret = -ENOMEM; | 3512 | ret = -ENOMEM; |
3421 | goto out_err1; | 3513 | goto out_err1; |
@@ -3516,7 +3608,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, | |||
3516 | property->dev = dev; | 3608 | property->dev = dev; |
3517 | 3609 | ||
3518 | if (num_values) { | 3610 | if (num_values) { |
3519 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); | 3611 | property->values = kcalloc(num_values, sizeof(uint64_t), |
3612 | GFP_KERNEL); | ||
3520 | if (!property->values) | 3613 | if (!property->values) |
3521 | goto fail; | 3614 | goto fail; |
3522 | } | 3615 | } |
@@ -3665,7 +3758,7 @@ static struct drm_property *property_create_range(struct drm_device *dev, | |||
3665 | } | 3758 | } |
3666 | 3759 | ||
3667 | /** | 3760 | /** |
3668 | * drm_property_create_range - create a new ranged property type | 3761 | * drm_property_create_range - create a new unsigned ranged property type |
3669 | * @dev: drm device | 3762 | * @dev: drm device |
3670 | * @flags: flags specifying the property type | 3763 | * @flags: flags specifying the property type |
3671 | * @name: name of the property | 3764 | * @name: name of the property |
@@ -3676,8 +3769,8 @@ static struct drm_property *property_create_range(struct drm_device *dev, | |||
3676 | * object with drm_object_attach_property. The returned property object must be | 3769 | * object with drm_object_attach_property. The returned property object must be |
3677 | * freed with drm_property_destroy. | 3770 | * freed with drm_property_destroy. |
3678 | * | 3771 | * |
3679 | * Userspace is allowed to set any integer value in the (min, max) range | 3772 | * Userspace is allowed to set any unsigned integer value in the (min, max) |
3680 | * inclusive. | 3773 | * range inclusive. |
3681 | * | 3774 | * |
3682 | * Returns: | 3775 | * Returns: |
3683 | * A pointer to the newly created property on success, NULL on failure. | 3776 | * A pointer to the newly created property on success, NULL on failure. |
@@ -3691,6 +3784,24 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags | |||
3691 | } | 3784 | } |
3692 | EXPORT_SYMBOL(drm_property_create_range); | 3785 | EXPORT_SYMBOL(drm_property_create_range); |
3693 | 3786 | ||
3787 | /** | ||
3788 | * drm_property_create_signed_range - create a new signed ranged property type | ||
3789 | * @dev: drm device | ||
3790 | * @flags: flags specifying the property type | ||
3791 | * @name: name of the property | ||
3792 | * @min: minimum value of the property | ||
3793 | * @max: maximum value of the property | ||
3794 | * | ||
3795 | * This creates a new generic drm property which can then be attached to a drm | ||
3796 | * object with drm_object_attach_property. The returned property object must be | ||
3797 | * freed with drm_property_destroy. | ||
3798 | * | ||
3799 | * Userspace is allowed to set any signed integer value in the (min, max) | ||
3800 | * range inclusive. | ||
3801 | * | ||
3802 | * Returns: | ||
3803 | * A pointer to the newly created property on success, NULL on failure. | ||
3804 | */ | ||
3694 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, | 3805 | struct drm_property *drm_property_create_signed_range(struct drm_device *dev, |
3695 | int flags, const char *name, | 3806 | int flags, const char *name, |
3696 | int64_t min, int64_t max) | 3807 | int64_t min, int64_t max) |
@@ -3700,6 +3811,23 @@ struct drm_property *drm_property_create_signed_range(struct drm_device *dev, | |||
3700 | } | 3811 | } |
3701 | EXPORT_SYMBOL(drm_property_create_signed_range); | 3812 | EXPORT_SYMBOL(drm_property_create_signed_range); |
3702 | 3813 | ||
3814 | /** | ||
3815 | * drm_property_create_object - create a new object property type | ||
3816 | * @dev: drm device | ||
3817 | * @flags: flags specifying the property type | ||
3818 | * @name: name of the property | ||
3819 | * @type: object type from DRM_MODE_OBJECT_* defines | ||
3820 | * | ||
3821 | * This creates a new generic drm property which can then be attached to a drm | ||
3822 | * object with drm_object_attach_property. The returned property object must be | ||
3823 | * freed with drm_property_destroy. | ||
3824 | * | ||
3825 | * Userspace is only allowed to set this to any property value of the given | ||
3826 | * @type. Only useful for atomic properties, which is enforced. | ||
3827 | * | ||
3828 | * Returns: | ||
3829 | * A pointer to the newly created property on success, NULL on failure. | ||
3830 | */ | ||
3703 | struct drm_property *drm_property_create_object(struct drm_device *dev, | 3831 | struct drm_property *drm_property_create_object(struct drm_device *dev, |
3704 | int flags, const char *name, uint32_t type) | 3832 | int flags, const char *name, uint32_t type) |
3705 | { | 3833 | { |
@@ -3707,6 +3835,9 @@ struct drm_property *drm_property_create_object(struct drm_device *dev, | |||
3707 | 3835 | ||
3708 | flags |= DRM_MODE_PROP_OBJECT; | 3836 | flags |= DRM_MODE_PROP_OBJECT; |
3709 | 3837 | ||
3838 | if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC))) | ||
3839 | return NULL; | ||
3840 | |||
3710 | property = drm_property_create(dev, flags, name, 1); | 3841 | property = drm_property_create(dev, flags, name, 1); |
3711 | if (!property) | 3842 | if (!property) |
3712 | return NULL; | 3843 | return NULL; |
@@ -3718,6 +3849,28 @@ struct drm_property *drm_property_create_object(struct drm_device *dev, | |||
3718 | EXPORT_SYMBOL(drm_property_create_object); | 3849 | EXPORT_SYMBOL(drm_property_create_object); |
3719 | 3850 | ||
3720 | /** | 3851 | /** |
3852 | * drm_property_create_bool - create a new boolean property type | ||
3853 | * @dev: drm device | ||
3854 | * @flags: flags specifying the property type | ||
3855 | * @name: name of the property | ||
3856 | * | ||
3857 | * This creates a new generic drm property which can then be attached to a drm | ||
3858 | * object with drm_object_attach_property. The returned property object must be | ||
3859 | * freed with drm_property_destroy. | ||
3860 | * | ||
3861 | * This is implemented as a ranged property with only {0, 1} as valid values. | ||
3862 | * | ||
3863 | * Returns: | ||
3864 | * A pointer to the newly created property on success, NULL on failure. | ||
3865 | */ | ||
3866 | struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags, | ||
3867 | const char *name) | ||
3868 | { | ||
3869 | return drm_property_create_range(dev, flags, name, 0, 1); | ||
3870 | } | ||
3871 | EXPORT_SYMBOL(drm_property_create_bool); | ||
3872 | |||
3873 | /** | ||
3721 | * drm_property_add_enum - add a possible value to an enumeration property | 3874 | * drm_property_add_enum - add a possible value to an enumeration property |
3722 | * @property: enumeration property to change | 3875 | * @property: enumeration property to change |
3723 | * @index: index of the new enumeration | 3876 | * @index: index of the new enumeration |
@@ -3822,9 +3975,11 @@ void drm_object_attach_property(struct drm_mode_object *obj, | |||
3822 | return; | 3975 | return; |
3823 | } | 3976 | } |
3824 | 3977 | ||
3825 | obj->properties->ids[count] = property->base.id; | 3978 | obj->properties->properties[count] = property; |
3826 | obj->properties->values[count] = init_val; | 3979 | obj->properties->values[count] = init_val; |
3827 | obj->properties->count++; | 3980 | obj->properties->count++; |
3981 | if (property->flags & DRM_MODE_PROP_ATOMIC) | ||
3982 | obj->properties->atomic_count++; | ||
3828 | } | 3983 | } |
3829 | EXPORT_SYMBOL(drm_object_attach_property); | 3984 | EXPORT_SYMBOL(drm_object_attach_property); |
3830 | 3985 | ||
@@ -3847,7 +4002,7 @@ int drm_object_property_set_value(struct drm_mode_object *obj, | |||
3847 | int i; | 4002 | int i; |
3848 | 4003 | ||
3849 | for (i = 0; i < obj->properties->count; i++) { | 4004 | for (i = 0; i < obj->properties->count; i++) { |
3850 | if (obj->properties->ids[i] == property->base.id) { | 4005 | if (obj->properties->properties[i] == property) { |
3851 | obj->properties->values[i] = val; | 4006 | obj->properties->values[i] = val; |
3852 | return 0; | 4007 | return 0; |
3853 | } | 4008 | } |
@@ -3876,8 +4031,16 @@ int drm_object_property_get_value(struct drm_mode_object *obj, | |||
3876 | { | 4031 | { |
3877 | int i; | 4032 | int i; |
3878 | 4033 | ||
4034 | /* read-only properties bypass atomic mechanism and still store | ||
4035 | * their value in obj->properties->values[].. mostly to avoid | ||
4036 | * having to deal w/ EDID and similar props in atomic paths: | ||
4037 | */ | ||
4038 | if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) && | ||
4039 | !(property->flags & DRM_MODE_PROP_IMMUTABLE)) | ||
4040 | return drm_atomic_get_property(obj, property, val); | ||
4041 | |||
3879 | for (i = 0; i < obj->properties->count; i++) { | 4042 | for (i = 0; i < obj->properties->count; i++) { |
3880 | if (obj->properties->ids[i] == property->base.id) { | 4043 | if (obj->properties->properties[i] == property) { |
3881 | *val = obj->properties->values[i]; | 4044 | *val = obj->properties->values[i]; |
3882 | return 0; | 4045 | return 0; |
3883 | } | 4046 | } |
@@ -4057,7 +4220,7 @@ int drm_mode_getblob_ioctl(struct drm_device *dev, | |||
4057 | 4220 | ||
4058 | if (out_resp->length == blob->length) { | 4221 | if (out_resp->length == blob->length) { |
4059 | blob_ptr = (void __user *)(unsigned long)out_resp->data; | 4222 | blob_ptr = (void __user *)(unsigned long)out_resp->data; |
4060 | if (copy_to_user(blob_ptr, blob->data, blob->length)){ | 4223 | if (copy_to_user(blob_ptr, blob->data, blob->length)) { |
4061 | ret = -EFAULT; | 4224 | ret = -EFAULT; |
4062 | goto done; | 4225 | goto done; |
4063 | } | 4226 | } |
@@ -4193,25 +4356,38 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, | |||
4193 | } | 4356 | } |
4194 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); | 4357 | EXPORT_SYMBOL(drm_mode_connector_update_edid_property); |
4195 | 4358 | ||
4196 | static bool drm_property_change_is_valid(struct drm_property *property, | 4359 | /* Some properties could refer to dynamic refcnt'd objects, or things that |
4197 | uint64_t value) | 4360 | * need special locking to handle lifetime issues (ie. to ensure the prop |
4361 | * value doesn't become invalid part way through the property update due to | ||
4362 | * race). The value returned by reference via 'obj' should be passed back | ||
4363 | * to drm_property_change_valid_put() after the property is set (and the | ||
4364 | * object to which the property is attached has a chance to take it's own | ||
4365 | * reference). | ||
4366 | */ | ||
4367 | bool drm_property_change_valid_get(struct drm_property *property, | ||
4368 | uint64_t value, struct drm_mode_object **ref) | ||
4198 | { | 4369 | { |
4370 | int i; | ||
4371 | |||
4199 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) | 4372 | if (property->flags & DRM_MODE_PROP_IMMUTABLE) |
4200 | return false; | 4373 | return false; |
4201 | 4374 | ||
4375 | *ref = NULL; | ||
4376 | |||
4202 | if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { | 4377 | if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) { |
4203 | if (value < property->values[0] || value > property->values[1]) | 4378 | if (value < property->values[0] || value > property->values[1]) |
4204 | return false; | 4379 | return false; |
4205 | return true; | 4380 | return true; |
4206 | } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) { | 4381 | } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) { |
4207 | int64_t svalue = U642I64(value); | 4382 | int64_t svalue = U642I64(value); |
4383 | |||
4208 | if (svalue < U642I64(property->values[0]) || | 4384 | if (svalue < U642I64(property->values[0]) || |
4209 | svalue > U642I64(property->values[1])) | 4385 | svalue > U642I64(property->values[1])) |
4210 | return false; | 4386 | return false; |
4211 | return true; | 4387 | return true; |
4212 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { | 4388 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) { |
4213 | int i; | ||
4214 | uint64_t valid_mask = 0; | 4389 | uint64_t valid_mask = 0; |
4390 | |||
4215 | for (i = 0; i < property->num_values; i++) | 4391 | for (i = 0; i < property->num_values; i++) |
4216 | valid_mask |= (1ULL << property->values[i]); | 4392 | valid_mask |= (1ULL << property->values[i]); |
4217 | return !(value & ~valid_mask); | 4393 | return !(value & ~valid_mask); |
@@ -4219,25 +4395,40 @@ static bool drm_property_change_is_valid(struct drm_property *property, | |||
4219 | /* Only the driver knows */ | 4395 | /* Only the driver knows */ |
4220 | return true; | 4396 | return true; |
4221 | } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { | 4397 | } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { |
4222 | struct drm_mode_object *obj; | ||
4223 | /* a zero value for an object property translates to null: */ | 4398 | /* a zero value for an object property translates to null: */ |
4224 | if (value == 0) | 4399 | if (value == 0) |
4225 | return true; | 4400 | return true; |
4226 | /* | 4401 | |
4227 | * NOTE: use _object_find() directly to bypass restriction on | 4402 | /* handle refcnt'd objects specially: */ |
4228 | * looking up refcnt'd objects (ie. fb's). For a refcnt'd | 4403 | if (property->values[0] == DRM_MODE_OBJECT_FB) { |
4229 | * object this could race against object finalization, so it | 4404 | struct drm_framebuffer *fb; |
4230 | * simply tells us that the object *was* valid. Which is good | 4405 | fb = drm_framebuffer_lookup(property->dev, value); |
4231 | * enough. | 4406 | if (fb) { |
4232 | */ | 4407 | *ref = &fb->base; |
4233 | obj = _object_find(property->dev, value, property->values[0]); | ||
4234 | return obj != NULL; | ||
4235 | } else { | ||
4236 | int i; | ||
4237 | for (i = 0; i < property->num_values; i++) | ||
4238 | if (property->values[i] == value) | ||
4239 | return true; | 4408 | return true; |
4240 | return false; | 4409 | } else { |
4410 | return false; | ||
4411 | } | ||
4412 | } else { | ||
4413 | return _object_find(property->dev, value, property->values[0]) != NULL; | ||
4414 | } | ||
4415 | } | ||
4416 | |||
4417 | for (i = 0; i < property->num_values; i++) | ||
4418 | if (property->values[i] == value) | ||
4419 | return true; | ||
4420 | return false; | ||
4421 | } | ||
4422 | |||
4423 | void drm_property_change_valid_put(struct drm_property *property, | ||
4424 | struct drm_mode_object *ref) | ||
4425 | { | ||
4426 | if (!ref) | ||
4427 | return; | ||
4428 | |||
4429 | if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { | ||
4430 | if (property->values[0] == DRM_MODE_OBJECT_FB) | ||
4431 | drm_framebuffer_unreference(obj_to_fb(ref)); | ||
4241 | } | 4432 | } |
4242 | } | 4433 | } |
4243 | 4434 | ||
@@ -4356,11 +4547,6 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
4356 | struct drm_mode_obj_get_properties *arg = data; | 4547 | struct drm_mode_obj_get_properties *arg = data; |
4357 | struct drm_mode_object *obj; | 4548 | struct drm_mode_object *obj; |
4358 | int ret = 0; | 4549 | int ret = 0; |
4359 | int i; | ||
4360 | int copied = 0; | ||
4361 | int props_count = 0; | ||
4362 | uint32_t __user *props_ptr; | ||
4363 | uint64_t __user *prop_values_ptr; | ||
4364 | 4550 | ||
4365 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 4551 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4366 | return -EINVAL; | 4552 | return -EINVAL; |
@@ -4377,30 +4563,11 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, | |||
4377 | goto out; | 4563 | goto out; |
4378 | } | 4564 | } |
4379 | 4565 | ||
4380 | props_count = obj->properties->count; | 4566 | ret = get_properties(obj, file_priv->atomic, |
4567 | (uint32_t __user *)(unsigned long)(arg->props_ptr), | ||
4568 | (uint64_t __user *)(unsigned long)(arg->prop_values_ptr), | ||
4569 | &arg->count_props); | ||
4381 | 4570 | ||
4382 | /* This ioctl is called twice, once to determine how much space is | ||
4383 | * needed, and the 2nd time to fill it. */ | ||
4384 | if ((arg->count_props >= props_count) && props_count) { | ||
4385 | copied = 0; | ||
4386 | props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); | ||
4387 | prop_values_ptr = (uint64_t __user *)(unsigned long) | ||
4388 | (arg->prop_values_ptr); | ||
4389 | for (i = 0; i < props_count; i++) { | ||
4390 | if (put_user(obj->properties->ids[i], | ||
4391 | props_ptr + copied)) { | ||
4392 | ret = -EFAULT; | ||
4393 | goto out; | ||
4394 | } | ||
4395 | if (put_user(obj->properties->values[i], | ||
4396 | prop_values_ptr + copied)) { | ||
4397 | ret = -EFAULT; | ||
4398 | goto out; | ||
4399 | } | ||
4400 | copied++; | ||
4401 | } | ||
4402 | } | ||
4403 | arg->count_props = props_count; | ||
4404 | out: | 4571 | out: |
4405 | drm_modeset_unlock_all(dev); | 4572 | drm_modeset_unlock_all(dev); |
4406 | return ret; | 4573 | return ret; |
@@ -4429,8 +4596,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
4429 | struct drm_mode_object *arg_obj; | 4596 | struct drm_mode_object *arg_obj; |
4430 | struct drm_mode_object *prop_obj; | 4597 | struct drm_mode_object *prop_obj; |
4431 | struct drm_property *property; | 4598 | struct drm_property *property; |
4432 | int ret = -EINVAL; | 4599 | int i, ret = -EINVAL; |
4433 | int i; | 4600 | struct drm_mode_object *ref; |
4434 | 4601 | ||
4435 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 4602 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4436 | return -EINVAL; | 4603 | return -EINVAL; |
@@ -4446,7 +4613,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
4446 | goto out; | 4613 | goto out; |
4447 | 4614 | ||
4448 | for (i = 0; i < arg_obj->properties->count; i++) | 4615 | for (i = 0; i < arg_obj->properties->count; i++) |
4449 | if (arg_obj->properties->ids[i] == arg->prop_id) | 4616 | if (arg_obj->properties->properties[i]->base.id == arg->prop_id) |
4450 | break; | 4617 | break; |
4451 | 4618 | ||
4452 | if (i == arg_obj->properties->count) | 4619 | if (i == arg_obj->properties->count) |
@@ -4460,7 +4627,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
4460 | } | 4627 | } |
4461 | property = obj_to_property(prop_obj); | 4628 | property = obj_to_property(prop_obj); |
4462 | 4629 | ||
4463 | if (!drm_property_change_is_valid(property, arg->value)) | 4630 | if (!drm_property_change_valid_get(property, arg->value, &ref)) |
4464 | goto out; | 4631 | goto out; |
4465 | 4632 | ||
4466 | switch (arg_obj->type) { | 4633 | switch (arg_obj->type) { |
@@ -4477,6 +4644,8 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, | |||
4477 | break; | 4644 | break; |
4478 | } | 4645 | } |
4479 | 4646 | ||
4647 | drm_property_change_valid_put(property, ref); | ||
4648 | |||
4480 | out: | 4649 | out: |
4481 | drm_modeset_unlock_all(dev); | 4650 | drm_modeset_unlock_all(dev); |
4482 | return ret; | 4651 | return ret; |
@@ -4526,7 +4695,8 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, | |||
4526 | { | 4695 | { |
4527 | crtc->gamma_size = gamma_size; | 4696 | crtc->gamma_size = gamma_size; |
4528 | 4697 | ||
4529 | crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); | 4698 | crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3, |
4699 | GFP_KERNEL); | ||
4530 | if (!crtc->gamma_store) { | 4700 | if (!crtc->gamma_store) { |
4531 | crtc->gamma_size = 0; | 4701 | crtc->gamma_size = 0; |
4532 | return -ENOMEM; | 4702 | return -ENOMEM; |
@@ -4741,23 +4911,23 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
4741 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { | 4911 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { |
4742 | ret = -ENOMEM; | 4912 | ret = -ENOMEM; |
4743 | spin_lock_irqsave(&dev->event_lock, flags); | 4913 | spin_lock_irqsave(&dev->event_lock, flags); |
4744 | if (file_priv->event_space < sizeof e->event) { | 4914 | if (file_priv->event_space < sizeof(e->event)) { |
4745 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4915 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4746 | goto out; | 4916 | goto out; |
4747 | } | 4917 | } |
4748 | file_priv->event_space -= sizeof e->event; | 4918 | file_priv->event_space -= sizeof(e->event); |
4749 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4919 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4750 | 4920 | ||
4751 | e = kzalloc(sizeof *e, GFP_KERNEL); | 4921 | e = kzalloc(sizeof(*e), GFP_KERNEL); |
4752 | if (e == NULL) { | 4922 | if (e == NULL) { |
4753 | spin_lock_irqsave(&dev->event_lock, flags); | 4923 | spin_lock_irqsave(&dev->event_lock, flags); |
4754 | file_priv->event_space += sizeof e->event; | 4924 | file_priv->event_space += sizeof(e->event); |
4755 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4925 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4756 | goto out; | 4926 | goto out; |
4757 | } | 4927 | } |
4758 | 4928 | ||
4759 | e->event.base.type = DRM_EVENT_FLIP_COMPLETE; | 4929 | e->event.base.type = DRM_EVENT_FLIP_COMPLETE; |
4760 | e->event.base.length = sizeof e->event; | 4930 | e->event.base.length = sizeof(e->event); |
4761 | e->event.user_data = page_flip->user_data; | 4931 | e->event.user_data = page_flip->user_data; |
4762 | e->base.event = &e->event.base; | 4932 | e->base.event = &e->event.base; |
4763 | e->base.file_priv = file_priv; | 4933 | e->base.file_priv = file_priv; |
@@ -4770,7 +4940,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, | |||
4770 | if (ret) { | 4940 | if (ret) { |
4771 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { | 4941 | if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { |
4772 | spin_lock_irqsave(&dev->event_lock, flags); | 4942 | spin_lock_irqsave(&dev->event_lock, flags); |
4773 | file_priv->event_space += sizeof e->event; | 4943 | file_priv->event_space += sizeof(e->event); |
4774 | spin_unlock_irqrestore(&dev->event_lock, flags); | 4944 | spin_unlock_irqrestore(&dev->event_lock, flags); |
4775 | kfree(e); | 4945 | kfree(e); |
4776 | } | 4946 | } |
@@ -5211,7 +5381,6 @@ void drm_mode_config_init(struct drm_device *dev) | |||
5211 | INIT_LIST_HEAD(&dev->mode_config.fb_list); | 5381 | INIT_LIST_HEAD(&dev->mode_config.fb_list); |
5212 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); | 5382 | INIT_LIST_HEAD(&dev->mode_config.crtc_list); |
5213 | INIT_LIST_HEAD(&dev->mode_config.connector_list); | 5383 | INIT_LIST_HEAD(&dev->mode_config.connector_list); |
5214 | INIT_LIST_HEAD(&dev->mode_config.bridge_list); | ||
5215 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); | 5384 | INIT_LIST_HEAD(&dev->mode_config.encoder_list); |
5216 | INIT_LIST_HEAD(&dev->mode_config.property_list); | 5385 | INIT_LIST_HEAD(&dev->mode_config.property_list); |
5217 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); | 5386 | INIT_LIST_HEAD(&dev->mode_config.property_blob_list); |
@@ -5220,8 +5389,7 @@ void drm_mode_config_init(struct drm_device *dev) | |||
5220 | idr_init(&dev->mode_config.tile_idr); | 5389 | idr_init(&dev->mode_config.tile_idr); |
5221 | 5390 | ||
5222 | drm_modeset_lock_all(dev); | 5391 | drm_modeset_lock_all(dev); |
5223 | drm_mode_create_standard_connector_properties(dev); | 5392 | drm_mode_create_standard_properties(dev); |
5224 | drm_mode_create_standard_plane_properties(dev); | ||
5225 | drm_modeset_unlock_all(dev); | 5393 | drm_modeset_unlock_all(dev); |
5226 | 5394 | ||
5227 | /* Just to be sure */ | 5395 | /* Just to be sure */ |
@@ -5252,7 +5420,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
5252 | struct drm_connector *connector, *ot; | 5420 | struct drm_connector *connector, *ot; |
5253 | struct drm_crtc *crtc, *ct; | 5421 | struct drm_crtc *crtc, *ct; |
5254 | struct drm_encoder *encoder, *enct; | 5422 | struct drm_encoder *encoder, *enct; |
5255 | struct drm_bridge *bridge, *brt; | ||
5256 | struct drm_framebuffer *fb, *fbt; | 5423 | struct drm_framebuffer *fb, *fbt; |
5257 | struct drm_property *property, *pt; | 5424 | struct drm_property *property, *pt; |
5258 | struct drm_property_blob *blob, *bt; | 5425 | struct drm_property_blob *blob, *bt; |
@@ -5263,11 +5430,6 @@ void drm_mode_config_cleanup(struct drm_device *dev) | |||
5263 | encoder->funcs->destroy(encoder); | 5430 | encoder->funcs->destroy(encoder); |
5264 | } | 5431 | } |
5265 | 5432 | ||
5266 | list_for_each_entry_safe(bridge, brt, | ||
5267 | &dev->mode_config.bridge_list, head) { | ||
5268 | bridge->funcs->destroy(bridge); | ||
5269 | } | ||
5270 | |||
5271 | list_for_each_entry_safe(connector, ot, | 5433 | list_for_each_entry_safe(connector, ot, |
5272 | &dev->mode_config.connector_list, head) { | 5434 | &dev->mode_config.connector_list, head) { |
5273 | connector->funcs->destroy(connector); | 5435 | connector->funcs->destroy(connector); |