Commit ed7951dc13aad4a14695ec8122e9f0e2ef25d39e

Authored by Lespiau, Damien
Committed by Dave Airlie
1 parent b9434d0f16

drm: Make the HPD status updates debug logs more readable

Instead of just printing "status updated from 1 to 2", make those enum
numbers immediately readable.

v2: Also patch output_poll_execute() (Daniel Vetter)
v3: Use drm_get_connector_status_name (Ville Syrjälä)

Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (for v1)
Signed-off-by: Dave Airlie <airlied@redhat.com>

Showing 2 changed files with 7 additions and 4 deletions Inline Diff

drivers/gpu/drm/drm_crtc.c
1 /* 1 /*
2 * Copyright (c) 2006-2008 Intel Corporation 2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 * Copyright (c) 2008 Red Hat Inc. 4 * Copyright (c) 2008 Red Hat Inc.
5 * 5 *
6 * DRM core CRTC related functions 6 * DRM core CRTC related functions
7 * 7 *
8 * Permission to use, copy, modify, distribute, and sell this software and its 8 * Permission to use, copy, modify, distribute, and sell this software and its
9 * documentation for any purpose is hereby granted without fee, provided that 9 * documentation for any purpose is hereby granted without fee, provided that
10 * the above copyright notice appear in all copies and that both that copyright 10 * the above copyright notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting documentation, and 11 * notice and this permission notice appear in supporting documentation, and
12 * that the name of the copyright holders not be used in advertising or 12 * that the name of the copyright holders not be used in advertising or
13 * publicity pertaining to distribution of the software without specific, 13 * publicity pertaining to distribution of the software without specific,
14 * written prior permission. The copyright holders make no representations 14 * written prior permission. The copyright holders make no representations
15 * about the suitability of this software for any purpose. It is provided "as 15 * about the suitability of this software for any purpose. It is provided "as
16 * is" without express or implied warranty. 16 * is" without express or implied warranty.
17 * 17 *
18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 23 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 * OF THIS SOFTWARE. 24 * OF THIS SOFTWARE.
25 * 25 *
26 * Authors: 26 * Authors:
27 * Keith Packard 27 * Keith Packard
28 * Eric Anholt <eric@anholt.net> 28 * Eric Anholt <eric@anholt.net>
29 * Dave Airlie <airlied@linux.ie> 29 * Dave Airlie <airlied@linux.ie>
30 * Jesse Barnes <jesse.barnes@intel.com> 30 * Jesse Barnes <jesse.barnes@intel.com>
31 */ 31 */
32 #include <linux/list.h> 32 #include <linux/list.h>
33 #include <linux/slab.h> 33 #include <linux/slab.h>
34 #include <linux/export.h> 34 #include <linux/export.h>
35 #include <drm/drmP.h> 35 #include <drm/drmP.h>
36 #include <drm/drm_crtc.h> 36 #include <drm/drm_crtc.h>
37 #include <drm/drm_edid.h> 37 #include <drm/drm_edid.h>
38 #include <drm/drm_fourcc.h> 38 #include <drm/drm_fourcc.h>
39 39
40 /** 40 /**
41 * drm_modeset_lock_all - take all modeset locks 41 * drm_modeset_lock_all - take all modeset locks
42 * @dev: drm device 42 * @dev: drm device
43 * 43 *
44 * This function takes all modeset locks, suitable where a more fine-grained 44 * This function takes all modeset locks, suitable where a more fine-grained
45 * scheme isn't (yet) implemented. 45 * scheme isn't (yet) implemented.
46 */ 46 */
47 void drm_modeset_lock_all(struct drm_device *dev) 47 void drm_modeset_lock_all(struct drm_device *dev)
48 { 48 {
49 struct drm_crtc *crtc; 49 struct drm_crtc *crtc;
50 50
51 mutex_lock(&dev->mode_config.mutex); 51 mutex_lock(&dev->mode_config.mutex);
52 52
53 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 53 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
54 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); 54 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
55 } 55 }
56 EXPORT_SYMBOL(drm_modeset_lock_all); 56 EXPORT_SYMBOL(drm_modeset_lock_all);
57 57
58 /** 58 /**
59 * drm_modeset_unlock_all - drop all modeset locks 59 * drm_modeset_unlock_all - drop all modeset locks
60 * @dev: device 60 * @dev: device
61 */ 61 */
62 void drm_modeset_unlock_all(struct drm_device *dev) 62 void drm_modeset_unlock_all(struct drm_device *dev)
63 { 63 {
64 struct drm_crtc *crtc; 64 struct drm_crtc *crtc;
65 65
66 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 66 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
67 mutex_unlock(&crtc->mutex); 67 mutex_unlock(&crtc->mutex);
68 68
69 mutex_unlock(&dev->mode_config.mutex); 69 mutex_unlock(&dev->mode_config.mutex);
70 } 70 }
71 EXPORT_SYMBOL(drm_modeset_unlock_all); 71 EXPORT_SYMBOL(drm_modeset_unlock_all);
72 72
73 /** 73 /**
74 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked 74 * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked
75 * @dev: device 75 * @dev: device
76 */ 76 */
77 void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) 77 void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
78 { 78 {
79 struct drm_crtc *crtc; 79 struct drm_crtc *crtc;
80 80
81 /* Locking is currently fubar in the panic handler. */ 81 /* Locking is currently fubar in the panic handler. */
82 if (oops_in_progress) 82 if (oops_in_progress)
83 return; 83 return;
84 84
85 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 85 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
86 WARN_ON(!mutex_is_locked(&crtc->mutex)); 86 WARN_ON(!mutex_is_locked(&crtc->mutex));
87 87
88 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 88 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
89 } 89 }
90 EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); 90 EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
91 91
92 /* Avoid boilerplate. I'm tired of typing. */ 92 /* Avoid boilerplate. I'm tired of typing. */
93 #define DRM_ENUM_NAME_FN(fnname, list) \ 93 #define DRM_ENUM_NAME_FN(fnname, list) \
94 char *fnname(int val) \ 94 char *fnname(int val) \
95 { \ 95 { \
96 int i; \ 96 int i; \
97 for (i = 0; i < ARRAY_SIZE(list); i++) { \ 97 for (i = 0; i < ARRAY_SIZE(list); i++) { \
98 if (list[i].type == val) \ 98 if (list[i].type == val) \
99 return list[i].name; \ 99 return list[i].name; \
100 } \ 100 } \
101 return "(unknown)"; \ 101 return "(unknown)"; \
102 } 102 }
103 103
104 /* 104 /*
105 * Global properties 105 * Global properties
106 */ 106 */
107 static struct drm_prop_enum_list drm_dpms_enum_list[] = 107 static struct drm_prop_enum_list drm_dpms_enum_list[] =
108 { { DRM_MODE_DPMS_ON, "On" }, 108 { { DRM_MODE_DPMS_ON, "On" },
109 { DRM_MODE_DPMS_STANDBY, "Standby" }, 109 { DRM_MODE_DPMS_STANDBY, "Standby" },
110 { DRM_MODE_DPMS_SUSPEND, "Suspend" }, 110 { DRM_MODE_DPMS_SUSPEND, "Suspend" },
111 { DRM_MODE_DPMS_OFF, "Off" } 111 { DRM_MODE_DPMS_OFF, "Off" }
112 }; 112 };
113 113
114 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list) 114 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
115 115
116 /* 116 /*
117 * Optional properties 117 * Optional properties
118 */ 118 */
119 static struct drm_prop_enum_list drm_scaling_mode_enum_list[] = 119 static struct drm_prop_enum_list drm_scaling_mode_enum_list[] =
120 { 120 {
121 { DRM_MODE_SCALE_NONE, "None" }, 121 { DRM_MODE_SCALE_NONE, "None" },
122 { DRM_MODE_SCALE_FULLSCREEN, "Full" }, 122 { DRM_MODE_SCALE_FULLSCREEN, "Full" },
123 { DRM_MODE_SCALE_CENTER, "Center" }, 123 { DRM_MODE_SCALE_CENTER, "Center" },
124 { DRM_MODE_SCALE_ASPECT, "Full aspect" }, 124 { DRM_MODE_SCALE_ASPECT, "Full aspect" },
125 }; 125 };
126 126
127 static struct drm_prop_enum_list drm_dithering_mode_enum_list[] = 127 static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
128 { 128 {
129 { DRM_MODE_DITHERING_OFF, "Off" }, 129 { DRM_MODE_DITHERING_OFF, "Off" },
130 { DRM_MODE_DITHERING_ON, "On" }, 130 { DRM_MODE_DITHERING_ON, "On" },
131 { DRM_MODE_DITHERING_AUTO, "Automatic" }, 131 { DRM_MODE_DITHERING_AUTO, "Automatic" },
132 }; 132 };
133 133
134 /* 134 /*
135 * Non-global properties, but "required" for certain connectors. 135 * Non-global properties, but "required" for certain connectors.
136 */ 136 */
137 static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = 137 static struct drm_prop_enum_list drm_dvi_i_select_enum_list[] =
138 { 138 {
139 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 139 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
140 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 140 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
141 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 141 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
142 }; 142 };
143 143
144 DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list) 144 DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
145 145
146 static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = 146 static struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] =
147 { 147 {
148 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ 148 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
149 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */ 149 { DRM_MODE_SUBCONNECTOR_DVID, "DVI-D" }, /* DVI-I */
150 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */ 150 { DRM_MODE_SUBCONNECTOR_DVIA, "DVI-A" }, /* DVI-I */
151 }; 151 };
152 152
153 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, 153 DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
154 drm_dvi_i_subconnector_enum_list) 154 drm_dvi_i_subconnector_enum_list)
155 155
156 static struct drm_prop_enum_list drm_tv_select_enum_list[] = 156 static struct drm_prop_enum_list drm_tv_select_enum_list[] =
157 { 157 {
158 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ 158 { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
159 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ 159 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
160 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ 160 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
161 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ 161 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
162 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ 162 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
163 }; 163 };
164 164
165 DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list) 165 DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
166 166
167 static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = 167 static struct drm_prop_enum_list drm_tv_subconnector_enum_list[] =
168 { 168 {
169 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */ 169 { DRM_MODE_SUBCONNECTOR_Unknown, "Unknown" }, /* DVI-I and TV-out */
170 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ 170 { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
171 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */ 171 { DRM_MODE_SUBCONNECTOR_SVIDEO, "SVIDEO" }, /* TV-out */
172 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */ 172 { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
173 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */ 173 { DRM_MODE_SUBCONNECTOR_SCART, "SCART" }, /* TV-out */
174 }; 174 };
175 175
176 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name, 176 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
177 drm_tv_subconnector_enum_list) 177 drm_tv_subconnector_enum_list)
178 178
179 static struct drm_prop_enum_list drm_dirty_info_enum_list[] = { 179 static struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
180 { DRM_MODE_DIRTY_OFF, "Off" }, 180 { DRM_MODE_DIRTY_OFF, "Off" },
181 { DRM_MODE_DIRTY_ON, "On" }, 181 { DRM_MODE_DIRTY_ON, "On" },
182 { DRM_MODE_DIRTY_ANNOTATE, "Annotate" }, 182 { DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
183 }; 183 };
184 184
185 struct drm_conn_prop_enum_list { 185 struct drm_conn_prop_enum_list {
186 int type; 186 int type;
187 char *name; 187 char *name;
188 int count; 188 int count;
189 }; 189 };
190 190
191 /* 191 /*
192 * Connector and encoder types. 192 * Connector and encoder types.
193 */ 193 */
194 static struct drm_conn_prop_enum_list drm_connector_enum_list[] = 194 static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
195 { { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 }, 195 { { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
196 { DRM_MODE_CONNECTOR_VGA, "VGA", 0 }, 196 { DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
197 { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 }, 197 { DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
198 { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 }, 198 { DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
199 { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 }, 199 { DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
200 { DRM_MODE_CONNECTOR_Composite, "Composite", 0 }, 200 { DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
201 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 }, 201 { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
202 { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 }, 202 { DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
203 { DRM_MODE_CONNECTOR_Component, "Component", 0 }, 203 { DRM_MODE_CONNECTOR_Component, "Component", 0 },
204 { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 }, 204 { DRM_MODE_CONNECTOR_9PinDIN, "DIN", 0 },
205 { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 }, 205 { DRM_MODE_CONNECTOR_DisplayPort, "DP", 0 },
206 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 }, 206 { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A", 0 },
207 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 }, 207 { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B", 0 },
208 { DRM_MODE_CONNECTOR_TV, "TV", 0 }, 208 { DRM_MODE_CONNECTOR_TV, "TV", 0 },
209 { DRM_MODE_CONNECTOR_eDP, "eDP", 0 }, 209 { DRM_MODE_CONNECTOR_eDP, "eDP", 0 },
210 { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0}, 210 { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual", 0},
211 }; 211 };
212 212
213 static struct drm_prop_enum_list drm_encoder_enum_list[] = 213 static struct drm_prop_enum_list drm_encoder_enum_list[] =
214 { { DRM_MODE_ENCODER_NONE, "None" }, 214 { { DRM_MODE_ENCODER_NONE, "None" },
215 { DRM_MODE_ENCODER_DAC, "DAC" }, 215 { DRM_MODE_ENCODER_DAC, "DAC" },
216 { DRM_MODE_ENCODER_TMDS, "TMDS" }, 216 { DRM_MODE_ENCODER_TMDS, "TMDS" },
217 { DRM_MODE_ENCODER_LVDS, "LVDS" }, 217 { DRM_MODE_ENCODER_LVDS, "LVDS" },
218 { DRM_MODE_ENCODER_TVDAC, "TV" }, 218 { DRM_MODE_ENCODER_TVDAC, "TV" },
219 { DRM_MODE_ENCODER_VIRTUAL, "Virtual" }, 219 { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
220 }; 220 };
221 221
222 char *drm_get_encoder_name(struct drm_encoder *encoder) 222 char *drm_get_encoder_name(struct drm_encoder *encoder)
223 { 223 {
224 static char buf[32]; 224 static char buf[32];
225 225
226 snprintf(buf, 32, "%s-%d", 226 snprintf(buf, 32, "%s-%d",
227 drm_encoder_enum_list[encoder->encoder_type].name, 227 drm_encoder_enum_list[encoder->encoder_type].name,
228 encoder->base.id); 228 encoder->base.id);
229 return buf; 229 return buf;
230 } 230 }
231 EXPORT_SYMBOL(drm_get_encoder_name); 231 EXPORT_SYMBOL(drm_get_encoder_name);
232 232
233 char *drm_get_connector_name(struct drm_connector *connector) 233 char *drm_get_connector_name(struct drm_connector *connector)
234 { 234 {
235 static char buf[32]; 235 static char buf[32];
236 236
237 snprintf(buf, 32, "%s-%d", 237 snprintf(buf, 32, "%s-%d",
238 drm_connector_enum_list[connector->connector_type].name, 238 drm_connector_enum_list[connector->connector_type].name,
239 connector->connector_type_id); 239 connector->connector_type_id);
240 return buf; 240 return buf;
241 } 241 }
242 EXPORT_SYMBOL(drm_get_connector_name); 242 EXPORT_SYMBOL(drm_get_connector_name);
243 243
244 char *drm_get_connector_status_name(enum drm_connector_status status) 244 char *drm_get_connector_status_name(enum drm_connector_status status)
245 { 245 {
246 if (status == connector_status_connected) 246 if (status == connector_status_connected)
247 return "connected"; 247 return "connected";
248 else if (status == connector_status_disconnected) 248 else if (status == connector_status_disconnected)
249 return "disconnected"; 249 return "disconnected";
250 else 250 else
251 return "unknown"; 251 return "unknown";
252 } 252 }
253 EXPORT_SYMBOL(drm_get_connector_status_name);
253 254
254 /** 255 /**
255 * drm_mode_object_get - allocate a new modeset identifier 256 * drm_mode_object_get - allocate a new modeset identifier
256 * @dev: DRM device 257 * @dev: DRM device
257 * @obj: object pointer, used to generate unique ID 258 * @obj: object pointer, used to generate unique ID
258 * @obj_type: object type 259 * @obj_type: object type
259 * 260 *
260 * Create a unique identifier based on @ptr in @dev's identifier space. Used 261 * Create a unique identifier based on @ptr in @dev's identifier space. Used
261 * for tracking modes, CRTCs and connectors. 262 * for tracking modes, CRTCs and connectors.
262 * 263 *
263 * RETURNS: 264 * RETURNS:
264 * New unique (relative to other objects in @dev) integer identifier for the 265 * New unique (relative to other objects in @dev) integer identifier for the
265 * object. 266 * object.
266 */ 267 */
267 static int drm_mode_object_get(struct drm_device *dev, 268 static int drm_mode_object_get(struct drm_device *dev,
268 struct drm_mode_object *obj, uint32_t obj_type) 269 struct drm_mode_object *obj, uint32_t obj_type)
269 { 270 {
270 int ret; 271 int ret;
271 272
272 mutex_lock(&dev->mode_config.idr_mutex); 273 mutex_lock(&dev->mode_config.idr_mutex);
273 ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL); 274 ret = idr_alloc(&dev->mode_config.crtc_idr, obj, 1, 0, GFP_KERNEL);
274 if (ret >= 0) { 275 if (ret >= 0) {
275 /* 276 /*
276 * Set up the object linking under the protection of the idr 277 * Set up the object linking under the protection of the idr
277 * lock so that other users can't see inconsistent state. 278 * lock so that other users can't see inconsistent state.
278 */ 279 */
279 obj->id = ret; 280 obj->id = ret;
280 obj->type = obj_type; 281 obj->type = obj_type;
281 } 282 }
282 mutex_unlock(&dev->mode_config.idr_mutex); 283 mutex_unlock(&dev->mode_config.idr_mutex);
283 284
284 return ret < 0 ? ret : 0; 285 return ret < 0 ? ret : 0;
285 } 286 }
286 287
287 /** 288 /**
288 * drm_mode_object_put - free a modeset identifer 289 * drm_mode_object_put - free a modeset identifer
289 * @dev: DRM device 290 * @dev: DRM device
290 * @object: object to free 291 * @object: object to free
291 * 292 *
292 * Free @id from @dev's unique identifier pool. 293 * Free @id from @dev's unique identifier pool.
293 */ 294 */
294 static void drm_mode_object_put(struct drm_device *dev, 295 static void drm_mode_object_put(struct drm_device *dev,
295 struct drm_mode_object *object) 296 struct drm_mode_object *object)
296 { 297 {
297 mutex_lock(&dev->mode_config.idr_mutex); 298 mutex_lock(&dev->mode_config.idr_mutex);
298 idr_remove(&dev->mode_config.crtc_idr, object->id); 299 idr_remove(&dev->mode_config.crtc_idr, object->id);
299 mutex_unlock(&dev->mode_config.idr_mutex); 300 mutex_unlock(&dev->mode_config.idr_mutex);
300 } 301 }
301 302
302 /** 303 /**
303 * drm_mode_object_find - look up a drm object with static lifetime 304 * drm_mode_object_find - look up a drm object with static lifetime
304 * @dev: drm device 305 * @dev: drm device
305 * @id: id of the mode object 306 * @id: id of the mode object
306 * @type: type of the mode object 307 * @type: type of the mode object
307 * 308 *
308 * Note that framebuffers cannot be looked up with this functions - since those 309 * Note that framebuffers cannot be looked up with this functions - since those
309 * are reference counted, they need special treatment. 310 * are reference counted, they need special treatment.
310 */ 311 */
311 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, 312 struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
312 uint32_t id, uint32_t type) 313 uint32_t id, uint32_t type)
313 { 314 {
314 struct drm_mode_object *obj = NULL; 315 struct drm_mode_object *obj = NULL;
315 316
316 /* Framebuffers are reference counted and need their own lookup 317 /* Framebuffers are reference counted and need their own lookup
317 * function.*/ 318 * function.*/
318 WARN_ON(type == DRM_MODE_OBJECT_FB); 319 WARN_ON(type == DRM_MODE_OBJECT_FB);
319 320
320 mutex_lock(&dev->mode_config.idr_mutex); 321 mutex_lock(&dev->mode_config.idr_mutex);
321 obj = idr_find(&dev->mode_config.crtc_idr, id); 322 obj = idr_find(&dev->mode_config.crtc_idr, id);
322 if (!obj || (obj->type != type) || (obj->id != id)) 323 if (!obj || (obj->type != type) || (obj->id != id))
323 obj = NULL; 324 obj = NULL;
324 mutex_unlock(&dev->mode_config.idr_mutex); 325 mutex_unlock(&dev->mode_config.idr_mutex);
325 326
326 return obj; 327 return obj;
327 } 328 }
328 EXPORT_SYMBOL(drm_mode_object_find); 329 EXPORT_SYMBOL(drm_mode_object_find);
329 330
330 /** 331 /**
331 * drm_framebuffer_init - initialize a framebuffer 332 * drm_framebuffer_init - initialize a framebuffer
332 * @dev: DRM device 333 * @dev: DRM device
333 * @fb: framebuffer to be initialized 334 * @fb: framebuffer to be initialized
334 * @funcs: ... with these functions 335 * @funcs: ... with these functions
335 * 336 *
336 * Allocates an ID for the framebuffer's parent mode object, sets its mode 337 * Allocates an ID for the framebuffer's parent mode object, sets its mode
337 * functions & device file and adds it to the master fd list. 338 * functions & device file and adds it to the master fd list.
338 * 339 *
339 * IMPORTANT: 340 * IMPORTANT:
340 * This functions publishes the fb and makes it available for concurrent access 341 * This functions publishes the fb and makes it available for concurrent access
341 * by other users. Which means by this point the fb _must_ be fully set up - 342 * by other users. Which means by this point the fb _must_ be fully set up -
342 * since all the fb attributes are invariant over its lifetime, no further 343 * since all the fb attributes are invariant over its lifetime, no further
343 * locking but only correct reference counting is required. 344 * locking but only correct reference counting is required.
344 * 345 *
345 * RETURNS: 346 * RETURNS:
346 * Zero on success, error code on failure. 347 * Zero on success, error code on failure.
347 */ 348 */
348 int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb, 349 int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
349 const struct drm_framebuffer_funcs *funcs) 350 const struct drm_framebuffer_funcs *funcs)
350 { 351 {
351 int ret; 352 int ret;
352 353
353 mutex_lock(&dev->mode_config.fb_lock); 354 mutex_lock(&dev->mode_config.fb_lock);
354 kref_init(&fb->refcount); 355 kref_init(&fb->refcount);
355 INIT_LIST_HEAD(&fb->filp_head); 356 INIT_LIST_HEAD(&fb->filp_head);
356 fb->dev = dev; 357 fb->dev = dev;
357 fb->funcs = funcs; 358 fb->funcs = funcs;
358 359
359 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB); 360 ret = drm_mode_object_get(dev, &fb->base, DRM_MODE_OBJECT_FB);
360 if (ret) 361 if (ret)
361 goto out; 362 goto out;
362 363
363 /* Grab the idr reference. */ 364 /* Grab the idr reference. */
364 drm_framebuffer_reference(fb); 365 drm_framebuffer_reference(fb);
365 366
366 dev->mode_config.num_fb++; 367 dev->mode_config.num_fb++;
367 list_add(&fb->head, &dev->mode_config.fb_list); 368 list_add(&fb->head, &dev->mode_config.fb_list);
368 out: 369 out:
369 mutex_unlock(&dev->mode_config.fb_lock); 370 mutex_unlock(&dev->mode_config.fb_lock);
370 371
371 return 0; 372 return 0;
372 } 373 }
373 EXPORT_SYMBOL(drm_framebuffer_init); 374 EXPORT_SYMBOL(drm_framebuffer_init);
374 375
375 static void drm_framebuffer_free(struct kref *kref) 376 static void drm_framebuffer_free(struct kref *kref)
376 { 377 {
377 struct drm_framebuffer *fb = 378 struct drm_framebuffer *fb =
378 container_of(kref, struct drm_framebuffer, refcount); 379 container_of(kref, struct drm_framebuffer, refcount);
379 fb->funcs->destroy(fb); 380 fb->funcs->destroy(fb);
380 } 381 }
381 382
382 static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev, 383 static struct drm_framebuffer *__drm_framebuffer_lookup(struct drm_device *dev,
383 uint32_t id) 384 uint32_t id)
384 { 385 {
385 struct drm_mode_object *obj = NULL; 386 struct drm_mode_object *obj = NULL;
386 struct drm_framebuffer *fb; 387 struct drm_framebuffer *fb;
387 388
388 mutex_lock(&dev->mode_config.idr_mutex); 389 mutex_lock(&dev->mode_config.idr_mutex);
389 obj = idr_find(&dev->mode_config.crtc_idr, id); 390 obj = idr_find(&dev->mode_config.crtc_idr, id);
390 if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id)) 391 if (!obj || (obj->type != DRM_MODE_OBJECT_FB) || (obj->id != id))
391 fb = NULL; 392 fb = NULL;
392 else 393 else
393 fb = obj_to_fb(obj); 394 fb = obj_to_fb(obj);
394 mutex_unlock(&dev->mode_config.idr_mutex); 395 mutex_unlock(&dev->mode_config.idr_mutex);
395 396
396 return fb; 397 return fb;
397 } 398 }
398 399
399 /** 400 /**
400 * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference 401 * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
401 * @dev: drm device 402 * @dev: drm device
402 * @id: id of the fb object 403 * @id: id of the fb object
403 * 404 *
404 * If successful, this grabs an additional reference to the framebuffer - 405 * If successful, this grabs an additional reference to the framebuffer -
405 * callers need to make sure to eventually unreference the returned framebuffer 406 * callers need to make sure to eventually unreference the returned framebuffer
406 * again. 407 * again.
407 */ 408 */
408 struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, 409 struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
409 uint32_t id) 410 uint32_t id)
410 { 411 {
411 struct drm_framebuffer *fb; 412 struct drm_framebuffer *fb;
412 413
413 mutex_lock(&dev->mode_config.fb_lock); 414 mutex_lock(&dev->mode_config.fb_lock);
414 fb = __drm_framebuffer_lookup(dev, id); 415 fb = __drm_framebuffer_lookup(dev, id);
415 if (fb) 416 if (fb)
416 drm_framebuffer_reference(fb); 417 drm_framebuffer_reference(fb);
417 mutex_unlock(&dev->mode_config.fb_lock); 418 mutex_unlock(&dev->mode_config.fb_lock);
418 419
419 return fb; 420 return fb;
420 } 421 }
421 EXPORT_SYMBOL(drm_framebuffer_lookup); 422 EXPORT_SYMBOL(drm_framebuffer_lookup);
422 423
423 /** 424 /**
424 * drm_framebuffer_unreference - unref a framebuffer 425 * drm_framebuffer_unreference - unref a framebuffer
425 * @fb: framebuffer to unref 426 * @fb: framebuffer to unref
426 * 427 *
427 * This functions decrements the fb's refcount and frees it if it drops to zero. 428 * This functions decrements the fb's refcount and frees it if it drops to zero.
428 */ 429 */
429 void drm_framebuffer_unreference(struct drm_framebuffer *fb) 430 void drm_framebuffer_unreference(struct drm_framebuffer *fb)
430 { 431 {
431 DRM_DEBUG("FB ID: %d\n", fb->base.id); 432 DRM_DEBUG("FB ID: %d\n", fb->base.id);
432 kref_put(&fb->refcount, drm_framebuffer_free); 433 kref_put(&fb->refcount, drm_framebuffer_free);
433 } 434 }
434 EXPORT_SYMBOL(drm_framebuffer_unreference); 435 EXPORT_SYMBOL(drm_framebuffer_unreference);
435 436
436 /** 437 /**
437 * drm_framebuffer_reference - incr the fb refcnt 438 * drm_framebuffer_reference - incr the fb refcnt
438 * @fb: framebuffer 439 * @fb: framebuffer
439 */ 440 */
440 void drm_framebuffer_reference(struct drm_framebuffer *fb) 441 void drm_framebuffer_reference(struct drm_framebuffer *fb)
441 { 442 {
442 DRM_DEBUG("FB ID: %d\n", fb->base.id); 443 DRM_DEBUG("FB ID: %d\n", fb->base.id);
443 kref_get(&fb->refcount); 444 kref_get(&fb->refcount);
444 } 445 }
445 EXPORT_SYMBOL(drm_framebuffer_reference); 446 EXPORT_SYMBOL(drm_framebuffer_reference);
446 447
447 static void drm_framebuffer_free_bug(struct kref *kref) 448 static void drm_framebuffer_free_bug(struct kref *kref)
448 { 449 {
449 BUG(); 450 BUG();
450 } 451 }
451 452
452 static void __drm_framebuffer_unreference(struct drm_framebuffer *fb) 453 static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
453 { 454 {
454 DRM_DEBUG("FB ID: %d\n", fb->base.id); 455 DRM_DEBUG("FB ID: %d\n", fb->base.id);
455 kref_put(&fb->refcount, drm_framebuffer_free_bug); 456 kref_put(&fb->refcount, drm_framebuffer_free_bug);
456 } 457 }
457 458
458 /* dev->mode_config.fb_lock must be held! */ 459 /* dev->mode_config.fb_lock must be held! */
459 static void __drm_framebuffer_unregister(struct drm_device *dev, 460 static void __drm_framebuffer_unregister(struct drm_device *dev,
460 struct drm_framebuffer *fb) 461 struct drm_framebuffer *fb)
461 { 462 {
462 mutex_lock(&dev->mode_config.idr_mutex); 463 mutex_lock(&dev->mode_config.idr_mutex);
463 idr_remove(&dev->mode_config.crtc_idr, fb->base.id); 464 idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
464 mutex_unlock(&dev->mode_config.idr_mutex); 465 mutex_unlock(&dev->mode_config.idr_mutex);
465 466
466 fb->base.id = 0; 467 fb->base.id = 0;
467 468
468 __drm_framebuffer_unreference(fb); 469 __drm_framebuffer_unreference(fb);
469 } 470 }
470 471
471 /** 472 /**
472 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr 473 * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
473 * @fb: fb to unregister 474 * @fb: fb to unregister
474 * 475 *
475 * Drivers need to call this when cleaning up driver-private framebuffers, e.g. 476 * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
476 * those used for fbdev. Note that the caller must hold a reference of it's own, 477 * those used for fbdev. Note that the caller must hold a reference of it's own,
477 * i.e. the object may not be destroyed through this call (since it'll lead to a 478 * i.e. the object may not be destroyed through this call (since it'll lead to a
478 * locking inversion). 479 * locking inversion).
479 */ 480 */
480 void drm_framebuffer_unregister_private(struct drm_framebuffer *fb) 481 void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
481 { 482 {
482 struct drm_device *dev = fb->dev; 483 struct drm_device *dev = fb->dev;
483 484
484 mutex_lock(&dev->mode_config.fb_lock); 485 mutex_lock(&dev->mode_config.fb_lock);
485 /* Mark fb as reaped and drop idr ref. */ 486 /* Mark fb as reaped and drop idr ref. */
486 __drm_framebuffer_unregister(dev, fb); 487 __drm_framebuffer_unregister(dev, fb);
487 mutex_unlock(&dev->mode_config.fb_lock); 488 mutex_unlock(&dev->mode_config.fb_lock);
488 } 489 }
489 EXPORT_SYMBOL(drm_framebuffer_unregister_private); 490 EXPORT_SYMBOL(drm_framebuffer_unregister_private);
490 491
491 /** 492 /**
492 * drm_framebuffer_cleanup - remove a framebuffer object 493 * drm_framebuffer_cleanup - remove a framebuffer object
493 * @fb: framebuffer to remove 494 * @fb: framebuffer to remove
494 * 495 *
495 * Cleanup references to a user-created framebuffer. This function is intended 496 * Cleanup references to a user-created framebuffer. This function is intended
496 * to be used from the drivers ->destroy callback. 497 * to be used from the drivers ->destroy callback.
497 * 498 *
498 * Note that this function does not remove the fb from active usuage - if it is 499 * Note that this function does not remove the fb from active usuage - if it is
499 * still used anywhere, hilarity can ensue since userspace could call getfb on 500 * still used anywhere, hilarity can ensue since userspace could call getfb on
500 * the id and get back -EINVAL. Obviously no concern at driver unload time. 501 * the id and get back -EINVAL. Obviously no concern at driver unload time.
501 * 502 *
502 * Also, the framebuffer will not be removed from the lookup idr - for 503 * Also, the framebuffer will not be removed from the lookup idr - for
503 * user-created framebuffers this will happen in in the rmfb ioctl. For 504 * user-created framebuffers this will happen in in the rmfb ioctl. For
504 * driver-private objects (e.g. for fbdev) drivers need to explicitly call 505 * driver-private objects (e.g. for fbdev) drivers need to explicitly call
505 * drm_framebuffer_unregister_private. 506 * drm_framebuffer_unregister_private.
506 */ 507 */
507 void drm_framebuffer_cleanup(struct drm_framebuffer *fb) 508 void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
508 { 509 {
509 struct drm_device *dev = fb->dev; 510 struct drm_device *dev = fb->dev;
510 511
511 mutex_lock(&dev->mode_config.fb_lock); 512 mutex_lock(&dev->mode_config.fb_lock);
512 list_del(&fb->head); 513 list_del(&fb->head);
513 dev->mode_config.num_fb--; 514 dev->mode_config.num_fb--;
514 mutex_unlock(&dev->mode_config.fb_lock); 515 mutex_unlock(&dev->mode_config.fb_lock);
515 } 516 }
516 EXPORT_SYMBOL(drm_framebuffer_cleanup); 517 EXPORT_SYMBOL(drm_framebuffer_cleanup);
517 518
518 /** 519 /**
519 * drm_framebuffer_remove - remove and unreference a framebuffer object 520 * drm_framebuffer_remove - remove and unreference a framebuffer object
520 * @fb: framebuffer to remove 521 * @fb: framebuffer to remove
521 * 522 *
522 * Scans all the CRTCs and planes in @dev's mode_config. If they're 523 * Scans all the CRTCs and planes in @dev's mode_config. If they're
523 * using @fb, removes it, setting it to NULL. Then drops the reference to the 524 * using @fb, removes it, setting it to NULL. Then drops the reference to the
524 * passed-in framebuffer. Might take the modeset locks. 525 * passed-in framebuffer. Might take the modeset locks.
525 * 526 *
526 * Note that this function optimizes the cleanup away if the caller holds the 527 * Note that this function optimizes the cleanup away if the caller holds the
527 * last reference to the framebuffer. It is also guaranteed to not take the 528 * last reference to the framebuffer. It is also guaranteed to not take the
528 * modeset locks in this case. 529 * modeset locks in this case.
529 */ 530 */
530 void drm_framebuffer_remove(struct drm_framebuffer *fb) 531 void drm_framebuffer_remove(struct drm_framebuffer *fb)
531 { 532 {
532 struct drm_device *dev = fb->dev; 533 struct drm_device *dev = fb->dev;
533 struct drm_crtc *crtc; 534 struct drm_crtc *crtc;
534 struct drm_plane *plane; 535 struct drm_plane *plane;
535 struct drm_mode_set set; 536 struct drm_mode_set set;
536 int ret; 537 int ret;
537 538
538 WARN_ON(!list_empty(&fb->filp_head)); 539 WARN_ON(!list_empty(&fb->filp_head));
539 540
540 /* 541 /*
541 * drm ABI mandates that we remove any deleted framebuffers from active 542 * drm ABI mandates that we remove any deleted framebuffers from active
542 * useage. But since most sane clients only remove framebuffers they no 543 * useage. But since most sane clients only remove framebuffers they no
543 * longer need, try to optimize this away. 544 * longer need, try to optimize this away.
544 * 545 *
545 * Since we're holding a reference ourselves, observing a refcount of 1 546 * Since we're holding a reference ourselves, observing a refcount of 1
546 * means that we're the last holder and can skip it. Also, the refcount 547 * means that we're the last holder and can skip it. Also, the refcount
547 * can never increase from 1 again, so we don't need any barriers or 548 * can never increase from 1 again, so we don't need any barriers or
548 * locks. 549 * locks.
549 * 550 *
550 * Note that userspace could try to race with use and instate a new 551 * Note that userspace could try to race with use and instate a new
551 * usage _after_ we've cleared all current ones. End result will be an 552 * usage _after_ we've cleared all current ones. End result will be an
552 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot 553 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
553 * in this manner. 554 * in this manner.
554 */ 555 */
555 if (atomic_read(&fb->refcount.refcount) > 1) { 556 if (atomic_read(&fb->refcount.refcount) > 1) {
556 drm_modeset_lock_all(dev); 557 drm_modeset_lock_all(dev);
557 /* remove from any CRTC */ 558 /* remove from any CRTC */
558 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 559 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
559 if (crtc->fb == fb) { 560 if (crtc->fb == fb) {
560 /* should turn off the crtc */ 561 /* should turn off the crtc */
561 memset(&set, 0, sizeof(struct drm_mode_set)); 562 memset(&set, 0, sizeof(struct drm_mode_set));
562 set.crtc = crtc; 563 set.crtc = crtc;
563 set.fb = NULL; 564 set.fb = NULL;
564 ret = drm_mode_set_config_internal(&set); 565 ret = drm_mode_set_config_internal(&set);
565 if (ret) 566 if (ret)
566 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); 567 DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
567 } 568 }
568 } 569 }
569 570
570 list_for_each_entry(plane, &dev->mode_config.plane_list, head) { 571 list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
571 if (plane->fb == fb) { 572 if (plane->fb == fb) {
572 /* should turn off the crtc */ 573 /* should turn off the crtc */
573 ret = plane->funcs->disable_plane(plane); 574 ret = plane->funcs->disable_plane(plane);
574 if (ret) 575 if (ret)
575 DRM_ERROR("failed to disable plane with busy fb\n"); 576 DRM_ERROR("failed to disable plane with busy fb\n");
576 /* disconnect the plane from the fb and crtc: */ 577 /* disconnect the plane from the fb and crtc: */
577 __drm_framebuffer_unreference(plane->fb); 578 __drm_framebuffer_unreference(plane->fb);
578 plane->fb = NULL; 579 plane->fb = NULL;
579 plane->crtc = NULL; 580 plane->crtc = NULL;
580 } 581 }
581 } 582 }
582 drm_modeset_unlock_all(dev); 583 drm_modeset_unlock_all(dev);
583 } 584 }
584 585
585 drm_framebuffer_unreference(fb); 586 drm_framebuffer_unreference(fb);
586 } 587 }
587 EXPORT_SYMBOL(drm_framebuffer_remove); 588 EXPORT_SYMBOL(drm_framebuffer_remove);
588 589
589 /** 590 /**
590 * drm_crtc_init - Initialise a new CRTC object 591 * drm_crtc_init - Initialise a new CRTC object
591 * @dev: DRM device 592 * @dev: DRM device
592 * @crtc: CRTC object to init 593 * @crtc: CRTC object to init
593 * @funcs: callbacks for the new CRTC 594 * @funcs: callbacks for the new CRTC
594 * 595 *
595 * Inits a new object created as base part of an driver crtc object. 596 * Inits a new object created as base part of an driver crtc object.
596 * 597 *
597 * RETURNS: 598 * RETURNS:
598 * Zero on success, error code on failure. 599 * Zero on success, error code on failure.
599 */ 600 */
600 int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, 601 int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
601 const struct drm_crtc_funcs *funcs) 602 const struct drm_crtc_funcs *funcs)
602 { 603 {
603 int ret; 604 int ret;
604 605
605 crtc->dev = dev; 606 crtc->dev = dev;
606 crtc->funcs = funcs; 607 crtc->funcs = funcs;
607 crtc->invert_dimensions = false; 608 crtc->invert_dimensions = false;
608 609
609 drm_modeset_lock_all(dev); 610 drm_modeset_lock_all(dev);
610 mutex_init(&crtc->mutex); 611 mutex_init(&crtc->mutex);
611 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); 612 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
612 613
613 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 614 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
614 if (ret) 615 if (ret)
615 goto out; 616 goto out;
616 617
617 crtc->base.properties = &crtc->properties; 618 crtc->base.properties = &crtc->properties;
618 619
619 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 620 list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
620 dev->mode_config.num_crtc++; 621 dev->mode_config.num_crtc++;
621 622
622 out: 623 out:
623 drm_modeset_unlock_all(dev); 624 drm_modeset_unlock_all(dev);
624 625
625 return ret; 626 return ret;
626 } 627 }
627 EXPORT_SYMBOL(drm_crtc_init); 628 EXPORT_SYMBOL(drm_crtc_init);
628 629
629 /** 630 /**
630 * drm_crtc_cleanup - Cleans up the core crtc usage. 631 * drm_crtc_cleanup - Cleans up the core crtc usage.
631 * @crtc: CRTC to cleanup 632 * @crtc: CRTC to cleanup
632 * 633 *
633 * Cleanup @crtc. Removes from drm modesetting space 634 * Cleanup @crtc. Removes from drm modesetting space
634 * does NOT free object, caller does that. 635 * does NOT free object, caller does that.
635 */ 636 */
636 void drm_crtc_cleanup(struct drm_crtc *crtc) 637 void drm_crtc_cleanup(struct drm_crtc *crtc)
637 { 638 {
638 struct drm_device *dev = crtc->dev; 639 struct drm_device *dev = crtc->dev;
639 640
640 kfree(crtc->gamma_store); 641 kfree(crtc->gamma_store);
641 crtc->gamma_store = NULL; 642 crtc->gamma_store = NULL;
642 643
643 drm_mode_object_put(dev, &crtc->base); 644 drm_mode_object_put(dev, &crtc->base);
644 list_del(&crtc->head); 645 list_del(&crtc->head);
645 dev->mode_config.num_crtc--; 646 dev->mode_config.num_crtc--;
646 } 647 }
647 EXPORT_SYMBOL(drm_crtc_cleanup); 648 EXPORT_SYMBOL(drm_crtc_cleanup);
648 649
649 /** 650 /**
650 * drm_mode_probed_add - add a mode to a connector's probed mode list 651 * drm_mode_probed_add - add a mode to a connector's probed mode list
651 * @connector: connector the new mode 652 * @connector: connector the new mode
652 * @mode: mode data 653 * @mode: mode data
653 * 654 *
654 * Add @mode to @connector's mode list for later use. 655 * Add @mode to @connector's mode list for later use.
655 */ 656 */
656 void drm_mode_probed_add(struct drm_connector *connector, 657 void drm_mode_probed_add(struct drm_connector *connector,
657 struct drm_display_mode *mode) 658 struct drm_display_mode *mode)
658 { 659 {
659 list_add(&mode->head, &connector->probed_modes); 660 list_add(&mode->head, &connector->probed_modes);
660 } 661 }
661 EXPORT_SYMBOL(drm_mode_probed_add); 662 EXPORT_SYMBOL(drm_mode_probed_add);
662 663
663 /** 664 /**
664 * drm_mode_remove - remove and free a mode 665 * drm_mode_remove - remove and free a mode
665 * @connector: connector list to modify 666 * @connector: connector list to modify
666 * @mode: mode to remove 667 * @mode: mode to remove
667 * 668 *
668 * Remove @mode from @connector's mode list, then free it. 669 * Remove @mode from @connector's mode list, then free it.
669 */ 670 */
670 void drm_mode_remove(struct drm_connector *connector, 671 void drm_mode_remove(struct drm_connector *connector,
671 struct drm_display_mode *mode) 672 struct drm_display_mode *mode)
672 { 673 {
673 list_del(&mode->head); 674 list_del(&mode->head);
674 drm_mode_destroy(connector->dev, mode); 675 drm_mode_destroy(connector->dev, mode);
675 } 676 }
676 EXPORT_SYMBOL(drm_mode_remove); 677 EXPORT_SYMBOL(drm_mode_remove);
677 678
678 /** 679 /**
679 * drm_connector_init - Init a preallocated connector 680 * drm_connector_init - Init a preallocated connector
680 * @dev: DRM device 681 * @dev: DRM device
681 * @connector: the connector to init 682 * @connector: the connector to init
682 * @funcs: callbacks for this connector 683 * @funcs: callbacks for this connector
683 * @connector_type: user visible type of the connector 684 * @connector_type: user visible type of the connector
684 * 685 *
685 * Initialises a preallocated connector. Connectors should be 686 * Initialises a preallocated connector. Connectors should be
686 * subclassed as part of driver connector objects. 687 * subclassed as part of driver connector objects.
687 * 688 *
688 * RETURNS: 689 * RETURNS:
689 * Zero on success, error code on failure. 690 * Zero on success, error code on failure.
690 */ 691 */
691 int drm_connector_init(struct drm_device *dev, 692 int drm_connector_init(struct drm_device *dev,
692 struct drm_connector *connector, 693 struct drm_connector *connector,
693 const struct drm_connector_funcs *funcs, 694 const struct drm_connector_funcs *funcs,
694 int connector_type) 695 int connector_type)
695 { 696 {
696 int ret; 697 int ret;
697 698
698 drm_modeset_lock_all(dev); 699 drm_modeset_lock_all(dev);
699 700
700 ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR); 701 ret = drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
701 if (ret) 702 if (ret)
702 goto out; 703 goto out;
703 704
704 connector->base.properties = &connector->properties; 705 connector->base.properties = &connector->properties;
705 connector->dev = dev; 706 connector->dev = dev;
706 connector->funcs = funcs; 707 connector->funcs = funcs;
707 connector->connector_type = connector_type; 708 connector->connector_type = connector_type;
708 connector->connector_type_id = 709 connector->connector_type_id =
709 ++drm_connector_enum_list[connector_type].count; /* TODO */ 710 ++drm_connector_enum_list[connector_type].count; /* TODO */
710 INIT_LIST_HEAD(&connector->probed_modes); 711 INIT_LIST_HEAD(&connector->probed_modes);
711 INIT_LIST_HEAD(&connector->modes); 712 INIT_LIST_HEAD(&connector->modes);
712 connector->edid_blob_ptr = NULL; 713 connector->edid_blob_ptr = NULL;
713 connector->status = connector_status_unknown; 714 connector->status = connector_status_unknown;
714 715
715 list_add_tail(&connector->head, &dev->mode_config.connector_list); 716 list_add_tail(&connector->head, &dev->mode_config.connector_list);
716 dev->mode_config.num_connector++; 717 dev->mode_config.num_connector++;
717 718
718 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL) 719 if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
719 drm_object_attach_property(&connector->base, 720 drm_object_attach_property(&connector->base,
720 dev->mode_config.edid_property, 721 dev->mode_config.edid_property,
721 0); 722 0);
722 723
723 drm_object_attach_property(&connector->base, 724 drm_object_attach_property(&connector->base,
724 dev->mode_config.dpms_property, 0); 725 dev->mode_config.dpms_property, 0);
725 726
726 out: 727 out:
727 drm_modeset_unlock_all(dev); 728 drm_modeset_unlock_all(dev);
728 729
729 return ret; 730 return ret;
730 } 731 }
731 EXPORT_SYMBOL(drm_connector_init); 732 EXPORT_SYMBOL(drm_connector_init);
732 733
733 /** 734 /**
734 * drm_connector_cleanup - cleans up an initialised connector 735 * drm_connector_cleanup - cleans up an initialised connector
735 * @connector: connector to cleanup 736 * @connector: connector to cleanup
736 * 737 *
737 * Cleans up the connector but doesn't free the object. 738 * Cleans up the connector but doesn't free the object.
738 */ 739 */
739 void drm_connector_cleanup(struct drm_connector *connector) 740 void drm_connector_cleanup(struct drm_connector *connector)
740 { 741 {
741 struct drm_device *dev = connector->dev; 742 struct drm_device *dev = connector->dev;
742 struct drm_display_mode *mode, *t; 743 struct drm_display_mode *mode, *t;
743 744
744 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) 745 list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
745 drm_mode_remove(connector, mode); 746 drm_mode_remove(connector, mode);
746 747
747 list_for_each_entry_safe(mode, t, &connector->modes, head) 748 list_for_each_entry_safe(mode, t, &connector->modes, head)
748 drm_mode_remove(connector, mode); 749 drm_mode_remove(connector, mode);
749 750
750 drm_mode_object_put(dev, &connector->base); 751 drm_mode_object_put(dev, &connector->base);
751 list_del(&connector->head); 752 list_del(&connector->head);
752 dev->mode_config.num_connector--; 753 dev->mode_config.num_connector--;
753 } 754 }
754 EXPORT_SYMBOL(drm_connector_cleanup); 755 EXPORT_SYMBOL(drm_connector_cleanup);
755 756
756 void drm_connector_unplug_all(struct drm_device *dev) 757 void drm_connector_unplug_all(struct drm_device *dev)
757 { 758 {
758 struct drm_connector *connector; 759 struct drm_connector *connector;
759 760
760 /* taking the mode config mutex ends up in a clash with sysfs */ 761 /* taking the mode config mutex ends up in a clash with sysfs */
761 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 762 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
762 drm_sysfs_connector_remove(connector); 763 drm_sysfs_connector_remove(connector);
763 764
764 } 765 }
765 EXPORT_SYMBOL(drm_connector_unplug_all); 766 EXPORT_SYMBOL(drm_connector_unplug_all);
766 767
767 int drm_encoder_init(struct drm_device *dev, 768 int drm_encoder_init(struct drm_device *dev,
768 struct drm_encoder *encoder, 769 struct drm_encoder *encoder,
769 const struct drm_encoder_funcs *funcs, 770 const struct drm_encoder_funcs *funcs,
770 int encoder_type) 771 int encoder_type)
771 { 772 {
772 int ret; 773 int ret;
773 774
774 drm_modeset_lock_all(dev); 775 drm_modeset_lock_all(dev);
775 776
776 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER); 777 ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
777 if (ret) 778 if (ret)
778 goto out; 779 goto out;
779 780
780 encoder->dev = dev; 781 encoder->dev = dev;
781 encoder->encoder_type = encoder_type; 782 encoder->encoder_type = encoder_type;
782 encoder->funcs = funcs; 783 encoder->funcs = funcs;
783 784
784 list_add_tail(&encoder->head, &dev->mode_config.encoder_list); 785 list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
785 dev->mode_config.num_encoder++; 786 dev->mode_config.num_encoder++;
786 787
787 out: 788 out:
788 drm_modeset_unlock_all(dev); 789 drm_modeset_unlock_all(dev);
789 790
790 return ret; 791 return ret;
791 } 792 }
792 EXPORT_SYMBOL(drm_encoder_init); 793 EXPORT_SYMBOL(drm_encoder_init);
793 794
794 void drm_encoder_cleanup(struct drm_encoder *encoder) 795 void drm_encoder_cleanup(struct drm_encoder *encoder)
795 { 796 {
796 struct drm_device *dev = encoder->dev; 797 struct drm_device *dev = encoder->dev;
797 drm_modeset_lock_all(dev); 798 drm_modeset_lock_all(dev);
798 drm_mode_object_put(dev, &encoder->base); 799 drm_mode_object_put(dev, &encoder->base);
799 list_del(&encoder->head); 800 list_del(&encoder->head);
800 dev->mode_config.num_encoder--; 801 dev->mode_config.num_encoder--;
801 drm_modeset_unlock_all(dev); 802 drm_modeset_unlock_all(dev);
802 } 803 }
803 EXPORT_SYMBOL(drm_encoder_cleanup); 804 EXPORT_SYMBOL(drm_encoder_cleanup);
804 805
805 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane, 806 int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
806 unsigned long possible_crtcs, 807 unsigned long possible_crtcs,
807 const struct drm_plane_funcs *funcs, 808 const struct drm_plane_funcs *funcs,
808 const uint32_t *formats, uint32_t format_count, 809 const uint32_t *formats, uint32_t format_count,
809 bool priv) 810 bool priv)
810 { 811 {
811 int ret; 812 int ret;
812 813
813 drm_modeset_lock_all(dev); 814 drm_modeset_lock_all(dev);
814 815
815 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE); 816 ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
816 if (ret) 817 if (ret)
817 goto out; 818 goto out;
818 819
819 plane->base.properties = &plane->properties; 820 plane->base.properties = &plane->properties;
820 plane->dev = dev; 821 plane->dev = dev;
821 plane->funcs = funcs; 822 plane->funcs = funcs;
822 plane->format_types = kmalloc(sizeof(uint32_t) * format_count, 823 plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
823 GFP_KERNEL); 824 GFP_KERNEL);
824 if (!plane->format_types) { 825 if (!plane->format_types) {
825 DRM_DEBUG_KMS("out of memory when allocating plane\n"); 826 DRM_DEBUG_KMS("out of memory when allocating plane\n");
826 drm_mode_object_put(dev, &plane->base); 827 drm_mode_object_put(dev, &plane->base);
827 ret = -ENOMEM; 828 ret = -ENOMEM;
828 goto out; 829 goto out;
829 } 830 }
830 831
831 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t)); 832 memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
832 plane->format_count = format_count; 833 plane->format_count = format_count;
833 plane->possible_crtcs = possible_crtcs; 834 plane->possible_crtcs = possible_crtcs;
834 835
835 /* private planes are not exposed to userspace, but depending on 836 /* private planes are not exposed to userspace, but depending on
836 * display hardware, might be convenient to allow sharing programming 837 * display hardware, might be convenient to allow sharing programming
837 * for the scanout engine with the crtc implementation. 838 * for the scanout engine with the crtc implementation.
838 */ 839 */
839 if (!priv) { 840 if (!priv) {
840 list_add_tail(&plane->head, &dev->mode_config.plane_list); 841 list_add_tail(&plane->head, &dev->mode_config.plane_list);
841 dev->mode_config.num_plane++; 842 dev->mode_config.num_plane++;
842 } else { 843 } else {
843 INIT_LIST_HEAD(&plane->head); 844 INIT_LIST_HEAD(&plane->head);
844 } 845 }
845 846
846 out: 847 out:
847 drm_modeset_unlock_all(dev); 848 drm_modeset_unlock_all(dev);
848 849
849 return ret; 850 return ret;
850 } 851 }
851 EXPORT_SYMBOL(drm_plane_init); 852 EXPORT_SYMBOL(drm_plane_init);
852 853
853 void drm_plane_cleanup(struct drm_plane *plane) 854 void drm_plane_cleanup(struct drm_plane *plane)
854 { 855 {
855 struct drm_device *dev = plane->dev; 856 struct drm_device *dev = plane->dev;
856 857
857 drm_modeset_lock_all(dev); 858 drm_modeset_lock_all(dev);
858 kfree(plane->format_types); 859 kfree(plane->format_types);
859 drm_mode_object_put(dev, &plane->base); 860 drm_mode_object_put(dev, &plane->base);
860 /* if not added to a list, it must be a private plane */ 861 /* if not added to a list, it must be a private plane */
861 if (!list_empty(&plane->head)) { 862 if (!list_empty(&plane->head)) {
862 list_del(&plane->head); 863 list_del(&plane->head);
863 dev->mode_config.num_plane--; 864 dev->mode_config.num_plane--;
864 } 865 }
865 drm_modeset_unlock_all(dev); 866 drm_modeset_unlock_all(dev);
866 } 867 }
867 EXPORT_SYMBOL(drm_plane_cleanup); 868 EXPORT_SYMBOL(drm_plane_cleanup);
868 869
869 /** 870 /**
870 * drm_mode_create - create a new display mode 871 * drm_mode_create - create a new display mode
871 * @dev: DRM device 872 * @dev: DRM device
872 * 873 *
873 * Create a new drm_display_mode, give it an ID, and return it. 874 * Create a new drm_display_mode, give it an ID, and return it.
874 * 875 *
875 * RETURNS: 876 * RETURNS:
876 * Pointer to new mode on success, NULL on error. 877 * Pointer to new mode on success, NULL on error.
877 */ 878 */
878 struct drm_display_mode *drm_mode_create(struct drm_device *dev) 879 struct drm_display_mode *drm_mode_create(struct drm_device *dev)
879 { 880 {
880 struct drm_display_mode *nmode; 881 struct drm_display_mode *nmode;
881 882
882 nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL); 883 nmode = kzalloc(sizeof(struct drm_display_mode), GFP_KERNEL);
883 if (!nmode) 884 if (!nmode)
884 return NULL; 885 return NULL;
885 886
886 if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) { 887 if (drm_mode_object_get(dev, &nmode->base, DRM_MODE_OBJECT_MODE)) {
887 kfree(nmode); 888 kfree(nmode);
888 return NULL; 889 return NULL;
889 } 890 }
890 891
891 return nmode; 892 return nmode;
892 } 893 }
893 EXPORT_SYMBOL(drm_mode_create); 894 EXPORT_SYMBOL(drm_mode_create);
894 895
895 /** 896 /**
896 * drm_mode_destroy - remove a mode 897 * drm_mode_destroy - remove a mode
897 * @dev: DRM device 898 * @dev: DRM device
898 * @mode: mode to remove 899 * @mode: mode to remove
899 * 900 *
900 * Free @mode's unique identifier, then free it. 901 * Free @mode's unique identifier, then free it.
901 */ 902 */
902 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode) 903 void drm_mode_destroy(struct drm_device *dev, struct drm_display_mode *mode)
903 { 904 {
904 if (!mode) 905 if (!mode)
905 return; 906 return;
906 907
907 drm_mode_object_put(dev, &mode->base); 908 drm_mode_object_put(dev, &mode->base);
908 909
909 kfree(mode); 910 kfree(mode);
910 } 911 }
911 EXPORT_SYMBOL(drm_mode_destroy); 912 EXPORT_SYMBOL(drm_mode_destroy);
912 913
913 static int drm_mode_create_standard_connector_properties(struct drm_device *dev) 914 static int drm_mode_create_standard_connector_properties(struct drm_device *dev)
914 { 915 {
915 struct drm_property *edid; 916 struct drm_property *edid;
916 struct drm_property *dpms; 917 struct drm_property *dpms;
917 918
918 /* 919 /*
919 * Standard properties (apply to all connectors) 920 * Standard properties (apply to all connectors)
920 */ 921 */
921 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB | 922 edid = drm_property_create(dev, DRM_MODE_PROP_BLOB |
922 DRM_MODE_PROP_IMMUTABLE, 923 DRM_MODE_PROP_IMMUTABLE,
923 "EDID", 0); 924 "EDID", 0);
924 dev->mode_config.edid_property = edid; 925 dev->mode_config.edid_property = edid;
925 926
926 dpms = drm_property_create_enum(dev, 0, 927 dpms = drm_property_create_enum(dev, 0,
927 "DPMS", drm_dpms_enum_list, 928 "DPMS", drm_dpms_enum_list,
928 ARRAY_SIZE(drm_dpms_enum_list)); 929 ARRAY_SIZE(drm_dpms_enum_list));
929 dev->mode_config.dpms_property = dpms; 930 dev->mode_config.dpms_property = dpms;
930 931
931 return 0; 932 return 0;
932 } 933 }
933 934
934 /** 935 /**
935 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties 936 * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
936 * @dev: DRM device 937 * @dev: DRM device
937 * 938 *
938 * Called by a driver the first time a DVI-I connector is made. 939 * Called by a driver the first time a DVI-I connector is made.
939 */ 940 */
940 int drm_mode_create_dvi_i_properties(struct drm_device *dev) 941 int drm_mode_create_dvi_i_properties(struct drm_device *dev)
941 { 942 {
942 struct drm_property *dvi_i_selector; 943 struct drm_property *dvi_i_selector;
943 struct drm_property *dvi_i_subconnector; 944 struct drm_property *dvi_i_subconnector;
944 945
945 if (dev->mode_config.dvi_i_select_subconnector_property) 946 if (dev->mode_config.dvi_i_select_subconnector_property)
946 return 0; 947 return 0;
947 948
948 dvi_i_selector = 949 dvi_i_selector =
949 drm_property_create_enum(dev, 0, 950 drm_property_create_enum(dev, 0,
950 "select subconnector", 951 "select subconnector",
951 drm_dvi_i_select_enum_list, 952 drm_dvi_i_select_enum_list,
952 ARRAY_SIZE(drm_dvi_i_select_enum_list)); 953 ARRAY_SIZE(drm_dvi_i_select_enum_list));
953 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector; 954 dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
954 955
955 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 956 dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
956 "subconnector", 957 "subconnector",
957 drm_dvi_i_subconnector_enum_list, 958 drm_dvi_i_subconnector_enum_list,
958 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list)); 959 ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
959 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector; 960 dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
960 961
961 return 0; 962 return 0;
962 } 963 }
963 EXPORT_SYMBOL(drm_mode_create_dvi_i_properties); 964 EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
964 965
965 /** 966 /**
966 * drm_create_tv_properties - create TV specific connector properties 967 * drm_create_tv_properties - create TV specific connector properties
967 * @dev: DRM device 968 * @dev: DRM device
968 * @num_modes: number of different TV formats (modes) supported 969 * @num_modes: number of different TV formats (modes) supported
969 * @modes: array of pointers to strings containing name of each format 970 * @modes: array of pointers to strings containing name of each format
970 * 971 *
971 * Called by a driver's TV initialization routine, this function creates 972 * Called by a driver's TV initialization routine, this function creates
972 * the TV specific connector properties for a given device. Caller is 973 * the TV specific connector properties for a given device. Caller is
973 * responsible for allocating a list of format names and passing them to 974 * responsible for allocating a list of format names and passing them to
974 * this routine. 975 * this routine.
975 */ 976 */
976 int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes, 977 int drm_mode_create_tv_properties(struct drm_device *dev, int num_modes,
977 char *modes[]) 978 char *modes[])
978 { 979 {
979 struct drm_property *tv_selector; 980 struct drm_property *tv_selector;
980 struct drm_property *tv_subconnector; 981 struct drm_property *tv_subconnector;
981 int i; 982 int i;
982 983
983 if (dev->mode_config.tv_select_subconnector_property) 984 if (dev->mode_config.tv_select_subconnector_property)
984 return 0; 985 return 0;
985 986
986 /* 987 /*
987 * Basic connector properties 988 * Basic connector properties
988 */ 989 */
989 tv_selector = drm_property_create_enum(dev, 0, 990 tv_selector = drm_property_create_enum(dev, 0,
990 "select subconnector", 991 "select subconnector",
991 drm_tv_select_enum_list, 992 drm_tv_select_enum_list,
992 ARRAY_SIZE(drm_tv_select_enum_list)); 993 ARRAY_SIZE(drm_tv_select_enum_list));
993 dev->mode_config.tv_select_subconnector_property = tv_selector; 994 dev->mode_config.tv_select_subconnector_property = tv_selector;
994 995
995 tv_subconnector = 996 tv_subconnector =
996 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 997 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
997 "subconnector", 998 "subconnector",
998 drm_tv_subconnector_enum_list, 999 drm_tv_subconnector_enum_list,
999 ARRAY_SIZE(drm_tv_subconnector_enum_list)); 1000 ARRAY_SIZE(drm_tv_subconnector_enum_list));
1000 dev->mode_config.tv_subconnector_property = tv_subconnector; 1001 dev->mode_config.tv_subconnector_property = tv_subconnector;
1001 1002
1002 /* 1003 /*
1003 * Other, TV specific properties: margins & TV modes. 1004 * Other, TV specific properties: margins & TV modes.
1004 */ 1005 */
1005 dev->mode_config.tv_left_margin_property = 1006 dev->mode_config.tv_left_margin_property =
1006 drm_property_create_range(dev, 0, "left margin", 0, 100); 1007 drm_property_create_range(dev, 0, "left margin", 0, 100);
1007 1008
1008 dev->mode_config.tv_right_margin_property = 1009 dev->mode_config.tv_right_margin_property =
1009 drm_property_create_range(dev, 0, "right margin", 0, 100); 1010 drm_property_create_range(dev, 0, "right margin", 0, 100);
1010 1011
1011 dev->mode_config.tv_top_margin_property = 1012 dev->mode_config.tv_top_margin_property =
1012 drm_property_create_range(dev, 0, "top margin", 0, 100); 1013 drm_property_create_range(dev, 0, "top margin", 0, 100);
1013 1014
1014 dev->mode_config.tv_bottom_margin_property = 1015 dev->mode_config.tv_bottom_margin_property =
1015 drm_property_create_range(dev, 0, "bottom margin", 0, 100); 1016 drm_property_create_range(dev, 0, "bottom margin", 0, 100);
1016 1017
1017 dev->mode_config.tv_mode_property = 1018 dev->mode_config.tv_mode_property =
1018 drm_property_create(dev, DRM_MODE_PROP_ENUM, 1019 drm_property_create(dev, DRM_MODE_PROP_ENUM,
1019 "mode", num_modes); 1020 "mode", num_modes);
1020 for (i = 0; i < num_modes; i++) 1021 for (i = 0; i < num_modes; i++)
1021 drm_property_add_enum(dev->mode_config.tv_mode_property, i, 1022 drm_property_add_enum(dev->mode_config.tv_mode_property, i,
1022 i, modes[i]); 1023 i, modes[i]);
1023 1024
1024 dev->mode_config.tv_brightness_property = 1025 dev->mode_config.tv_brightness_property =
1025 drm_property_create_range(dev, 0, "brightness", 0, 100); 1026 drm_property_create_range(dev, 0, "brightness", 0, 100);
1026 1027
1027 dev->mode_config.tv_contrast_property = 1028 dev->mode_config.tv_contrast_property =
1028 drm_property_create_range(dev, 0, "contrast", 0, 100); 1029 drm_property_create_range(dev, 0, "contrast", 0, 100);
1029 1030
1030 dev->mode_config.tv_flicker_reduction_property = 1031 dev->mode_config.tv_flicker_reduction_property =
1031 drm_property_create_range(dev, 0, "flicker reduction", 0, 100); 1032 drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
1032 1033
1033 dev->mode_config.tv_overscan_property = 1034 dev->mode_config.tv_overscan_property =
1034 drm_property_create_range(dev, 0, "overscan", 0, 100); 1035 drm_property_create_range(dev, 0, "overscan", 0, 100);
1035 1036
1036 dev->mode_config.tv_saturation_property = 1037 dev->mode_config.tv_saturation_property =
1037 drm_property_create_range(dev, 0, "saturation", 0, 100); 1038 drm_property_create_range(dev, 0, "saturation", 0, 100);
1038 1039
1039 dev->mode_config.tv_hue_property = 1040 dev->mode_config.tv_hue_property =
1040 drm_property_create_range(dev, 0, "hue", 0, 100); 1041 drm_property_create_range(dev, 0, "hue", 0, 100);
1041 1042
1042 return 0; 1043 return 0;
1043 } 1044 }
1044 EXPORT_SYMBOL(drm_mode_create_tv_properties); 1045 EXPORT_SYMBOL(drm_mode_create_tv_properties);
1045 1046
1046 /** 1047 /**
1047 * drm_mode_create_scaling_mode_property - create scaling mode property 1048 * drm_mode_create_scaling_mode_property - create scaling mode property
1048 * @dev: DRM device 1049 * @dev: DRM device
1049 * 1050 *
1050 * Called by a driver the first time it's needed, must be attached to desired 1051 * Called by a driver the first time it's needed, must be attached to desired
1051 * connectors. 1052 * connectors.
1052 */ 1053 */
1053 int drm_mode_create_scaling_mode_property(struct drm_device *dev) 1054 int drm_mode_create_scaling_mode_property(struct drm_device *dev)
1054 { 1055 {
1055 struct drm_property *scaling_mode; 1056 struct drm_property *scaling_mode;
1056 1057
1057 if (dev->mode_config.scaling_mode_property) 1058 if (dev->mode_config.scaling_mode_property)
1058 return 0; 1059 return 0;
1059 1060
1060 scaling_mode = 1061 scaling_mode =
1061 drm_property_create_enum(dev, 0, "scaling mode", 1062 drm_property_create_enum(dev, 0, "scaling mode",
1062 drm_scaling_mode_enum_list, 1063 drm_scaling_mode_enum_list,
1063 ARRAY_SIZE(drm_scaling_mode_enum_list)); 1064 ARRAY_SIZE(drm_scaling_mode_enum_list));
1064 1065
1065 dev->mode_config.scaling_mode_property = scaling_mode; 1066 dev->mode_config.scaling_mode_property = scaling_mode;
1066 1067
1067 return 0; 1068 return 0;
1068 } 1069 }
1069 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); 1070 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
1070 1071
1071 /** 1072 /**
1072 * drm_mode_create_dithering_property - create dithering property 1073 * drm_mode_create_dithering_property - create dithering property
1073 * @dev: DRM device 1074 * @dev: DRM device
1074 * 1075 *
1075 * Called by a driver the first time it's needed, must be attached to desired 1076 * Called by a driver the first time it's needed, must be attached to desired
1076 * connectors. 1077 * connectors.
1077 */ 1078 */
1078 int drm_mode_create_dithering_property(struct drm_device *dev) 1079 int drm_mode_create_dithering_property(struct drm_device *dev)
1079 { 1080 {
1080 struct drm_property *dithering_mode; 1081 struct drm_property *dithering_mode;
1081 1082
1082 if (dev->mode_config.dithering_mode_property) 1083 if (dev->mode_config.dithering_mode_property)
1083 return 0; 1084 return 0;
1084 1085
1085 dithering_mode = 1086 dithering_mode =
1086 drm_property_create_enum(dev, 0, "dithering", 1087 drm_property_create_enum(dev, 0, "dithering",
1087 drm_dithering_mode_enum_list, 1088 drm_dithering_mode_enum_list,
1088 ARRAY_SIZE(drm_dithering_mode_enum_list)); 1089 ARRAY_SIZE(drm_dithering_mode_enum_list));
1089 dev->mode_config.dithering_mode_property = dithering_mode; 1090 dev->mode_config.dithering_mode_property = dithering_mode;
1090 1091
1091 return 0; 1092 return 0;
1092 } 1093 }
1093 EXPORT_SYMBOL(drm_mode_create_dithering_property); 1094 EXPORT_SYMBOL(drm_mode_create_dithering_property);
1094 1095
1095 /** 1096 /**
1096 * drm_mode_create_dirty_property - create dirty property 1097 * drm_mode_create_dirty_property - create dirty property
1097 * @dev: DRM device 1098 * @dev: DRM device
1098 * 1099 *
1099 * Called by a driver the first time it's needed, must be attached to desired 1100 * Called by a driver the first time it's needed, must be attached to desired
1100 * connectors. 1101 * connectors.
1101 */ 1102 */
1102 int drm_mode_create_dirty_info_property(struct drm_device *dev) 1103 int drm_mode_create_dirty_info_property(struct drm_device *dev)
1103 { 1104 {
1104 struct drm_property *dirty_info; 1105 struct drm_property *dirty_info;
1105 1106
1106 if (dev->mode_config.dirty_info_property) 1107 if (dev->mode_config.dirty_info_property)
1107 return 0; 1108 return 0;
1108 1109
1109 dirty_info = 1110 dirty_info =
1110 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE, 1111 drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
1111 "dirty", 1112 "dirty",
1112 drm_dirty_info_enum_list, 1113 drm_dirty_info_enum_list,
1113 ARRAY_SIZE(drm_dirty_info_enum_list)); 1114 ARRAY_SIZE(drm_dirty_info_enum_list));
1114 dev->mode_config.dirty_info_property = dirty_info; 1115 dev->mode_config.dirty_info_property = dirty_info;
1115 1116
1116 return 0; 1117 return 0;
1117 } 1118 }
1118 EXPORT_SYMBOL(drm_mode_create_dirty_info_property); 1119 EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
1119 1120
1120 static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group) 1121 static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
1121 { 1122 {
1122 uint32_t total_objects = 0; 1123 uint32_t total_objects = 0;
1123 1124
1124 total_objects += dev->mode_config.num_crtc; 1125 total_objects += dev->mode_config.num_crtc;
1125 total_objects += dev->mode_config.num_connector; 1126 total_objects += dev->mode_config.num_connector;
1126 total_objects += dev->mode_config.num_encoder; 1127 total_objects += dev->mode_config.num_encoder;
1127 1128
1128 group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL); 1129 group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
1129 if (!group->id_list) 1130 if (!group->id_list)
1130 return -ENOMEM; 1131 return -ENOMEM;
1131 1132
1132 group->num_crtcs = 0; 1133 group->num_crtcs = 0;
1133 group->num_connectors = 0; 1134 group->num_connectors = 0;
1134 group->num_encoders = 0; 1135 group->num_encoders = 0;
1135 return 0; 1136 return 0;
1136 } 1137 }
1137 1138
1138 int drm_mode_group_init_legacy_group(struct drm_device *dev, 1139 int drm_mode_group_init_legacy_group(struct drm_device *dev,
1139 struct drm_mode_group *group) 1140 struct drm_mode_group *group)
1140 { 1141 {
1141 struct drm_crtc *crtc; 1142 struct drm_crtc *crtc;
1142 struct drm_encoder *encoder; 1143 struct drm_encoder *encoder;
1143 struct drm_connector *connector; 1144 struct drm_connector *connector;
1144 int ret; 1145 int ret;
1145 1146
1146 if ((ret = drm_mode_group_init(dev, group))) 1147 if ((ret = drm_mode_group_init(dev, group)))
1147 return ret; 1148 return ret;
1148 1149
1149 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 1150 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
1150 group->id_list[group->num_crtcs++] = crtc->base.id; 1151 group->id_list[group->num_crtcs++] = crtc->base.id;
1151 1152
1152 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 1153 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
1153 group->id_list[group->num_crtcs + group->num_encoders++] = 1154 group->id_list[group->num_crtcs + group->num_encoders++] =
1154 encoder->base.id; 1155 encoder->base.id;
1155 1156
1156 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 1157 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
1157 group->id_list[group->num_crtcs + group->num_encoders + 1158 group->id_list[group->num_crtcs + group->num_encoders +
1158 group->num_connectors++] = connector->base.id; 1159 group->num_connectors++] = connector->base.id;
1159 1160
1160 return 0; 1161 return 0;
1161 } 1162 }
1162 EXPORT_SYMBOL(drm_mode_group_init_legacy_group); 1163 EXPORT_SYMBOL(drm_mode_group_init_legacy_group);
1163 1164
1164 /** 1165 /**
1165 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo 1166 * drm_crtc_convert_to_umode - convert a drm_display_mode into a modeinfo
1166 * @out: drm_mode_modeinfo struct to return to the user 1167 * @out: drm_mode_modeinfo struct to return to the user
1167 * @in: drm_display_mode to use 1168 * @in: drm_display_mode to use
1168 * 1169 *
1169 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to 1170 * Convert a drm_display_mode into a drm_mode_modeinfo structure to return to
1170 * the user. 1171 * the user.
1171 */ 1172 */
1172 static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, 1173 static void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
1173 const struct drm_display_mode *in) 1174 const struct drm_display_mode *in)
1174 { 1175 {
1175 WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX || 1176 WARN(in->hdisplay > USHRT_MAX || in->hsync_start > USHRT_MAX ||
1176 in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX || 1177 in->hsync_end > USHRT_MAX || in->htotal > USHRT_MAX ||
1177 in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX || 1178 in->hskew > USHRT_MAX || in->vdisplay > USHRT_MAX ||
1178 in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX || 1179 in->vsync_start > USHRT_MAX || in->vsync_end > USHRT_MAX ||
1179 in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX, 1180 in->vtotal > USHRT_MAX || in->vscan > USHRT_MAX,
1180 "timing values too large for mode info\n"); 1181 "timing values too large for mode info\n");
1181 1182
1182 out->clock = in->clock; 1183 out->clock = in->clock;
1183 out->hdisplay = in->hdisplay; 1184 out->hdisplay = in->hdisplay;
1184 out->hsync_start = in->hsync_start; 1185 out->hsync_start = in->hsync_start;
1185 out->hsync_end = in->hsync_end; 1186 out->hsync_end = in->hsync_end;
1186 out->htotal = in->htotal; 1187 out->htotal = in->htotal;
1187 out->hskew = in->hskew; 1188 out->hskew = in->hskew;
1188 out->vdisplay = in->vdisplay; 1189 out->vdisplay = in->vdisplay;
1189 out->vsync_start = in->vsync_start; 1190 out->vsync_start = in->vsync_start;
1190 out->vsync_end = in->vsync_end; 1191 out->vsync_end = in->vsync_end;
1191 out->vtotal = in->vtotal; 1192 out->vtotal = in->vtotal;
1192 out->vscan = in->vscan; 1193 out->vscan = in->vscan;
1193 out->vrefresh = in->vrefresh; 1194 out->vrefresh = in->vrefresh;
1194 out->flags = in->flags; 1195 out->flags = in->flags;
1195 out->type = in->type; 1196 out->type = in->type;
1196 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1197 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1197 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1198 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1198 } 1199 }
1199 1200
1200 /** 1201 /**
1201 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode 1202 * drm_crtc_convert_to_umode - convert a modeinfo into a drm_display_mode
1202 * @out: drm_display_mode to return to the user 1203 * @out: drm_display_mode to return to the user
1203 * @in: drm_mode_modeinfo to use 1204 * @in: drm_mode_modeinfo to use
1204 * 1205 *
1205 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to 1206 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
1206 * the caller. 1207 * the caller.
1207 * 1208 *
1208 * RETURNS: 1209 * RETURNS:
1209 * Zero on success, errno on failure. 1210 * Zero on success, errno on failure.
1210 */ 1211 */
1211 static int drm_crtc_convert_umode(struct drm_display_mode *out, 1212 static int drm_crtc_convert_umode(struct drm_display_mode *out,
1212 const struct drm_mode_modeinfo *in) 1213 const struct drm_mode_modeinfo *in)
1213 { 1214 {
1214 if (in->clock > INT_MAX || in->vrefresh > INT_MAX) 1215 if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
1215 return -ERANGE; 1216 return -ERANGE;
1216 1217
1217 out->clock = in->clock; 1218 out->clock = in->clock;
1218 out->hdisplay = in->hdisplay; 1219 out->hdisplay = in->hdisplay;
1219 out->hsync_start = in->hsync_start; 1220 out->hsync_start = in->hsync_start;
1220 out->hsync_end = in->hsync_end; 1221 out->hsync_end = in->hsync_end;
1221 out->htotal = in->htotal; 1222 out->htotal = in->htotal;
1222 out->hskew = in->hskew; 1223 out->hskew = in->hskew;
1223 out->vdisplay = in->vdisplay; 1224 out->vdisplay = in->vdisplay;
1224 out->vsync_start = in->vsync_start; 1225 out->vsync_start = in->vsync_start;
1225 out->vsync_end = in->vsync_end; 1226 out->vsync_end = in->vsync_end;
1226 out->vtotal = in->vtotal; 1227 out->vtotal = in->vtotal;
1227 out->vscan = in->vscan; 1228 out->vscan = in->vscan;
1228 out->vrefresh = in->vrefresh; 1229 out->vrefresh = in->vrefresh;
1229 out->flags = in->flags; 1230 out->flags = in->flags;
1230 out->type = in->type; 1231 out->type = in->type;
1231 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); 1232 strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
1232 out->name[DRM_DISPLAY_MODE_LEN-1] = 0; 1233 out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1233 1234
1234 return 0; 1235 return 0;
1235 } 1236 }
1236 1237
1237 /** 1238 /**
1238 * drm_mode_getresources - get graphics configuration 1239 * drm_mode_getresources - get graphics configuration
1239 * @dev: drm device for the ioctl 1240 * @dev: drm device for the ioctl
1240 * @data: data pointer for the ioctl 1241 * @data: data pointer for the ioctl
1241 * @file_priv: drm file for the ioctl call 1242 * @file_priv: drm file for the ioctl call
1242 * 1243 *
1243 * Construct a set of configuration description structures and return 1244 * Construct a set of configuration description structures and return
1244 * them to the user, including CRTC, connector and framebuffer configuration. 1245 * them to the user, including CRTC, connector and framebuffer configuration.
1245 * 1246 *
1246 * Called by the user via ioctl. 1247 * Called by the user via ioctl.
1247 * 1248 *
1248 * RETURNS: 1249 * RETURNS:
1249 * Zero on success, errno on failure. 1250 * Zero on success, errno on failure.
1250 */ 1251 */
1251 int drm_mode_getresources(struct drm_device *dev, void *data, 1252 int drm_mode_getresources(struct drm_device *dev, void *data,
1252 struct drm_file *file_priv) 1253 struct drm_file *file_priv)
1253 { 1254 {
1254 struct drm_mode_card_res *card_res = data; 1255 struct drm_mode_card_res *card_res = data;
1255 struct list_head *lh; 1256 struct list_head *lh;
1256 struct drm_framebuffer *fb; 1257 struct drm_framebuffer *fb;
1257 struct drm_connector *connector; 1258 struct drm_connector *connector;
1258 struct drm_crtc *crtc; 1259 struct drm_crtc *crtc;
1259 struct drm_encoder *encoder; 1260 struct drm_encoder *encoder;
1260 int ret = 0; 1261 int ret = 0;
1261 int connector_count = 0; 1262 int connector_count = 0;
1262 int crtc_count = 0; 1263 int crtc_count = 0;
1263 int fb_count = 0; 1264 int fb_count = 0;
1264 int encoder_count = 0; 1265 int encoder_count = 0;
1265 int copied = 0, i; 1266 int copied = 0, i;
1266 uint32_t __user *fb_id; 1267 uint32_t __user *fb_id;
1267 uint32_t __user *crtc_id; 1268 uint32_t __user *crtc_id;
1268 uint32_t __user *connector_id; 1269 uint32_t __user *connector_id;
1269 uint32_t __user *encoder_id; 1270 uint32_t __user *encoder_id;
1270 struct drm_mode_group *mode_group; 1271 struct drm_mode_group *mode_group;
1271 1272
1272 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1273 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1273 return -EINVAL; 1274 return -EINVAL;
1274 1275
1275 1276
1276 mutex_lock(&file_priv->fbs_lock); 1277 mutex_lock(&file_priv->fbs_lock);
1277 /* 1278 /*
1278 * For the non-control nodes we need to limit the list of resources 1279 * For the non-control nodes we need to limit the list of resources
1279 * by IDs in the group list for this node 1280 * by IDs in the group list for this node
1280 */ 1281 */
1281 list_for_each(lh, &file_priv->fbs) 1282 list_for_each(lh, &file_priv->fbs)
1282 fb_count++; 1283 fb_count++;
1283 1284
1284 /* handle this in 4 parts */ 1285 /* handle this in 4 parts */
1285 /* FBs */ 1286 /* FBs */
1286 if (card_res->count_fbs >= fb_count) { 1287 if (card_res->count_fbs >= fb_count) {
1287 copied = 0; 1288 copied = 0;
1288 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; 1289 fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
1289 list_for_each_entry(fb, &file_priv->fbs, filp_head) { 1290 list_for_each_entry(fb, &file_priv->fbs, filp_head) {
1290 if (put_user(fb->base.id, fb_id + copied)) { 1291 if (put_user(fb->base.id, fb_id + copied)) {
1291 mutex_unlock(&file_priv->fbs_lock); 1292 mutex_unlock(&file_priv->fbs_lock);
1292 return -EFAULT; 1293 return -EFAULT;
1293 } 1294 }
1294 copied++; 1295 copied++;
1295 } 1296 }
1296 } 1297 }
1297 card_res->count_fbs = fb_count; 1298 card_res->count_fbs = fb_count;
1298 mutex_unlock(&file_priv->fbs_lock); 1299 mutex_unlock(&file_priv->fbs_lock);
1299 1300
1300 drm_modeset_lock_all(dev); 1301 drm_modeset_lock_all(dev);
1301 mode_group = &file_priv->master->minor->mode_group; 1302 mode_group = &file_priv->master->minor->mode_group;
1302 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1303 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1303 1304
1304 list_for_each(lh, &dev->mode_config.crtc_list) 1305 list_for_each(lh, &dev->mode_config.crtc_list)
1305 crtc_count++; 1306 crtc_count++;
1306 1307
1307 list_for_each(lh, &dev->mode_config.connector_list) 1308 list_for_each(lh, &dev->mode_config.connector_list)
1308 connector_count++; 1309 connector_count++;
1309 1310
1310 list_for_each(lh, &dev->mode_config.encoder_list) 1311 list_for_each(lh, &dev->mode_config.encoder_list)
1311 encoder_count++; 1312 encoder_count++;
1312 } else { 1313 } else {
1313 1314
1314 crtc_count = mode_group->num_crtcs; 1315 crtc_count = mode_group->num_crtcs;
1315 connector_count = mode_group->num_connectors; 1316 connector_count = mode_group->num_connectors;
1316 encoder_count = mode_group->num_encoders; 1317 encoder_count = mode_group->num_encoders;
1317 } 1318 }
1318 1319
1319 card_res->max_height = dev->mode_config.max_height; 1320 card_res->max_height = dev->mode_config.max_height;
1320 card_res->min_height = dev->mode_config.min_height; 1321 card_res->min_height = dev->mode_config.min_height;
1321 card_res->max_width = dev->mode_config.max_width; 1322 card_res->max_width = dev->mode_config.max_width;
1322 card_res->min_width = dev->mode_config.min_width; 1323 card_res->min_width = dev->mode_config.min_width;
1323 1324
1324 /* CRTCs */ 1325 /* CRTCs */
1325 if (card_res->count_crtcs >= crtc_count) { 1326 if (card_res->count_crtcs >= crtc_count) {
1326 copied = 0; 1327 copied = 0;
1327 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr; 1328 crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
1328 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1329 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1329 list_for_each_entry(crtc, &dev->mode_config.crtc_list, 1330 list_for_each_entry(crtc, &dev->mode_config.crtc_list,
1330 head) { 1331 head) {
1331 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1332 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1332 if (put_user(crtc->base.id, crtc_id + copied)) { 1333 if (put_user(crtc->base.id, crtc_id + copied)) {
1333 ret = -EFAULT; 1334 ret = -EFAULT;
1334 goto out; 1335 goto out;
1335 } 1336 }
1336 copied++; 1337 copied++;
1337 } 1338 }
1338 } else { 1339 } else {
1339 for (i = 0; i < mode_group->num_crtcs; i++) { 1340 for (i = 0; i < mode_group->num_crtcs; i++) {
1340 if (put_user(mode_group->id_list[i], 1341 if (put_user(mode_group->id_list[i],
1341 crtc_id + copied)) { 1342 crtc_id + copied)) {
1342 ret = -EFAULT; 1343 ret = -EFAULT;
1343 goto out; 1344 goto out;
1344 } 1345 }
1345 copied++; 1346 copied++;
1346 } 1347 }
1347 } 1348 }
1348 } 1349 }
1349 card_res->count_crtcs = crtc_count; 1350 card_res->count_crtcs = crtc_count;
1350 1351
1351 /* Encoders */ 1352 /* Encoders */
1352 if (card_res->count_encoders >= encoder_count) { 1353 if (card_res->count_encoders >= encoder_count) {
1353 copied = 0; 1354 copied = 0;
1354 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr; 1355 encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
1355 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1356 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1356 list_for_each_entry(encoder, 1357 list_for_each_entry(encoder,
1357 &dev->mode_config.encoder_list, 1358 &dev->mode_config.encoder_list,
1358 head) { 1359 head) {
1359 DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id, 1360 DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
1360 drm_get_encoder_name(encoder)); 1361 drm_get_encoder_name(encoder));
1361 if (put_user(encoder->base.id, encoder_id + 1362 if (put_user(encoder->base.id, encoder_id +
1362 copied)) { 1363 copied)) {
1363 ret = -EFAULT; 1364 ret = -EFAULT;
1364 goto out; 1365 goto out;
1365 } 1366 }
1366 copied++; 1367 copied++;
1367 } 1368 }
1368 } else { 1369 } else {
1369 for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) { 1370 for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
1370 if (put_user(mode_group->id_list[i], 1371 if (put_user(mode_group->id_list[i],
1371 encoder_id + copied)) { 1372 encoder_id + copied)) {
1372 ret = -EFAULT; 1373 ret = -EFAULT;
1373 goto out; 1374 goto out;
1374 } 1375 }
1375 copied++; 1376 copied++;
1376 } 1377 }
1377 1378
1378 } 1379 }
1379 } 1380 }
1380 card_res->count_encoders = encoder_count; 1381 card_res->count_encoders = encoder_count;
1381 1382
1382 /* Connectors */ 1383 /* Connectors */
1383 if (card_res->count_connectors >= connector_count) { 1384 if (card_res->count_connectors >= connector_count) {
1384 copied = 0; 1385 copied = 0;
1385 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr; 1386 connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
1386 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) { 1387 if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
1387 list_for_each_entry(connector, 1388 list_for_each_entry(connector,
1388 &dev->mode_config.connector_list, 1389 &dev->mode_config.connector_list,
1389 head) { 1390 head) {
1390 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 1391 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
1391 connector->base.id, 1392 connector->base.id,
1392 drm_get_connector_name(connector)); 1393 drm_get_connector_name(connector));
1393 if (put_user(connector->base.id, 1394 if (put_user(connector->base.id,
1394 connector_id + copied)) { 1395 connector_id + copied)) {
1395 ret = -EFAULT; 1396 ret = -EFAULT;
1396 goto out; 1397 goto out;
1397 } 1398 }
1398 copied++; 1399 copied++;
1399 } 1400 }
1400 } else { 1401 } else {
1401 int start = mode_group->num_crtcs + 1402 int start = mode_group->num_crtcs +
1402 mode_group->num_encoders; 1403 mode_group->num_encoders;
1403 for (i = start; i < start + mode_group->num_connectors; i++) { 1404 for (i = start; i < start + mode_group->num_connectors; i++) {
1404 if (put_user(mode_group->id_list[i], 1405 if (put_user(mode_group->id_list[i],
1405 connector_id + copied)) { 1406 connector_id + copied)) {
1406 ret = -EFAULT; 1407 ret = -EFAULT;
1407 goto out; 1408 goto out;
1408 } 1409 }
1409 copied++; 1410 copied++;
1410 } 1411 }
1411 } 1412 }
1412 } 1413 }
1413 card_res->count_connectors = connector_count; 1414 card_res->count_connectors = connector_count;
1414 1415
1415 DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs, 1416 DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
1416 card_res->count_connectors, card_res->count_encoders); 1417 card_res->count_connectors, card_res->count_encoders);
1417 1418
1418 out: 1419 out:
1419 drm_modeset_unlock_all(dev); 1420 drm_modeset_unlock_all(dev);
1420 return ret; 1421 return ret;
1421 } 1422 }
1422 1423
1423 /** 1424 /**
1424 * drm_mode_getcrtc - get CRTC configuration 1425 * drm_mode_getcrtc - get CRTC configuration
1425 * @dev: drm device for the ioctl 1426 * @dev: drm device for the ioctl
1426 * @data: data pointer for the ioctl 1427 * @data: data pointer for the ioctl
1427 * @file_priv: drm file for the ioctl call 1428 * @file_priv: drm file for the ioctl call
1428 * 1429 *
1429 * Construct a CRTC configuration structure to return to the user. 1430 * Construct a CRTC configuration structure to return to the user.
1430 * 1431 *
1431 * Called by the user via ioctl. 1432 * Called by the user via ioctl.
1432 * 1433 *
1433 * RETURNS: 1434 * RETURNS:
1434 * Zero on success, errno on failure. 1435 * Zero on success, errno on failure.
1435 */ 1436 */
1436 int drm_mode_getcrtc(struct drm_device *dev, 1437 int drm_mode_getcrtc(struct drm_device *dev,
1437 void *data, struct drm_file *file_priv) 1438 void *data, struct drm_file *file_priv)
1438 { 1439 {
1439 struct drm_mode_crtc *crtc_resp = data; 1440 struct drm_mode_crtc *crtc_resp = data;
1440 struct drm_crtc *crtc; 1441 struct drm_crtc *crtc;
1441 struct drm_mode_object *obj; 1442 struct drm_mode_object *obj;
1442 int ret = 0; 1443 int ret = 0;
1443 1444
1444 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1445 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1445 return -EINVAL; 1446 return -EINVAL;
1446 1447
1447 drm_modeset_lock_all(dev); 1448 drm_modeset_lock_all(dev);
1448 1449
1449 obj = drm_mode_object_find(dev, crtc_resp->crtc_id, 1450 obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
1450 DRM_MODE_OBJECT_CRTC); 1451 DRM_MODE_OBJECT_CRTC);
1451 if (!obj) { 1452 if (!obj) {
1452 ret = -EINVAL; 1453 ret = -EINVAL;
1453 goto out; 1454 goto out;
1454 } 1455 }
1455 crtc = obj_to_crtc(obj); 1456 crtc = obj_to_crtc(obj);
1456 1457
1457 crtc_resp->x = crtc->x; 1458 crtc_resp->x = crtc->x;
1458 crtc_resp->y = crtc->y; 1459 crtc_resp->y = crtc->y;
1459 crtc_resp->gamma_size = crtc->gamma_size; 1460 crtc_resp->gamma_size = crtc->gamma_size;
1460 if (crtc->fb) 1461 if (crtc->fb)
1461 crtc_resp->fb_id = crtc->fb->base.id; 1462 crtc_resp->fb_id = crtc->fb->base.id;
1462 else 1463 else
1463 crtc_resp->fb_id = 0; 1464 crtc_resp->fb_id = 0;
1464 1465
1465 if (crtc->enabled) { 1466 if (crtc->enabled) {
1466 1467
1467 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode); 1468 drm_crtc_convert_to_umode(&crtc_resp->mode, &crtc->mode);
1468 crtc_resp->mode_valid = 1; 1469 crtc_resp->mode_valid = 1;
1469 1470
1470 } else { 1471 } else {
1471 crtc_resp->mode_valid = 0; 1472 crtc_resp->mode_valid = 0;
1472 } 1473 }
1473 1474
1474 out: 1475 out:
1475 drm_modeset_unlock_all(dev); 1476 drm_modeset_unlock_all(dev);
1476 return ret; 1477 return ret;
1477 } 1478 }
1478 1479
1479 /** 1480 /**
1480 * drm_mode_getconnector - get connector configuration 1481 * drm_mode_getconnector - get connector configuration
1481 * @dev: drm device for the ioctl 1482 * @dev: drm device for the ioctl
1482 * @data: data pointer for the ioctl 1483 * @data: data pointer for the ioctl
1483 * @file_priv: drm file for the ioctl call 1484 * @file_priv: drm file for the ioctl call
1484 * 1485 *
1485 * Construct a connector configuration structure to return to the user. 1486 * Construct a connector configuration structure to return to the user.
1486 * 1487 *
1487 * Called by the user via ioctl. 1488 * Called by the user via ioctl.
1488 * 1489 *
1489 * RETURNS: 1490 * RETURNS:
1490 * Zero on success, errno on failure. 1491 * Zero on success, errno on failure.
1491 */ 1492 */
1492 int drm_mode_getconnector(struct drm_device *dev, void *data, 1493 int drm_mode_getconnector(struct drm_device *dev, void *data,
1493 struct drm_file *file_priv) 1494 struct drm_file *file_priv)
1494 { 1495 {
1495 struct drm_mode_get_connector *out_resp = data; 1496 struct drm_mode_get_connector *out_resp = data;
1496 struct drm_mode_object *obj; 1497 struct drm_mode_object *obj;
1497 struct drm_connector *connector; 1498 struct drm_connector *connector;
1498 struct drm_display_mode *mode; 1499 struct drm_display_mode *mode;
1499 int mode_count = 0; 1500 int mode_count = 0;
1500 int props_count = 0; 1501 int props_count = 0;
1501 int encoders_count = 0; 1502 int encoders_count = 0;
1502 int ret = 0; 1503 int ret = 0;
1503 int copied = 0; 1504 int copied = 0;
1504 int i; 1505 int i;
1505 struct drm_mode_modeinfo u_mode; 1506 struct drm_mode_modeinfo u_mode;
1506 struct drm_mode_modeinfo __user *mode_ptr; 1507 struct drm_mode_modeinfo __user *mode_ptr;
1507 uint32_t __user *prop_ptr; 1508 uint32_t __user *prop_ptr;
1508 uint64_t __user *prop_values; 1509 uint64_t __user *prop_values;
1509 uint32_t __user *encoder_ptr; 1510 uint32_t __user *encoder_ptr;
1510 1511
1511 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1512 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1512 return -EINVAL; 1513 return -EINVAL;
1513 1514
1514 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); 1515 memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
1515 1516
1516 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); 1517 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
1517 1518
1518 mutex_lock(&dev->mode_config.mutex); 1519 mutex_lock(&dev->mode_config.mutex);
1519 1520
1520 obj = drm_mode_object_find(dev, out_resp->connector_id, 1521 obj = drm_mode_object_find(dev, out_resp->connector_id,
1521 DRM_MODE_OBJECT_CONNECTOR); 1522 DRM_MODE_OBJECT_CONNECTOR);
1522 if (!obj) { 1523 if (!obj) {
1523 ret = -EINVAL; 1524 ret = -EINVAL;
1524 goto out; 1525 goto out;
1525 } 1526 }
1526 connector = obj_to_connector(obj); 1527 connector = obj_to_connector(obj);
1527 1528
1528 props_count = connector->properties.count; 1529 props_count = connector->properties.count;
1529 1530
1530 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1531 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1531 if (connector->encoder_ids[i] != 0) { 1532 if (connector->encoder_ids[i] != 0) {
1532 encoders_count++; 1533 encoders_count++;
1533 } 1534 }
1534 } 1535 }
1535 1536
1536 if (out_resp->count_modes == 0) { 1537 if (out_resp->count_modes == 0) {
1537 connector->funcs->fill_modes(connector, 1538 connector->funcs->fill_modes(connector,
1538 dev->mode_config.max_width, 1539 dev->mode_config.max_width,
1539 dev->mode_config.max_height); 1540 dev->mode_config.max_height);
1540 } 1541 }
1541 1542
1542 /* delayed so we get modes regardless of pre-fill_modes state */ 1543 /* delayed so we get modes regardless of pre-fill_modes state */
1543 list_for_each_entry(mode, &connector->modes, head) 1544 list_for_each_entry(mode, &connector->modes, head)
1544 mode_count++; 1545 mode_count++;
1545 1546
1546 out_resp->connector_id = connector->base.id; 1547 out_resp->connector_id = connector->base.id;
1547 out_resp->connector_type = connector->connector_type; 1548 out_resp->connector_type = connector->connector_type;
1548 out_resp->connector_type_id = connector->connector_type_id; 1549 out_resp->connector_type_id = connector->connector_type_id;
1549 out_resp->mm_width = connector->display_info.width_mm; 1550 out_resp->mm_width = connector->display_info.width_mm;
1550 out_resp->mm_height = connector->display_info.height_mm; 1551 out_resp->mm_height = connector->display_info.height_mm;
1551 out_resp->subpixel = connector->display_info.subpixel_order; 1552 out_resp->subpixel = connector->display_info.subpixel_order;
1552 out_resp->connection = connector->status; 1553 out_resp->connection = connector->status;
1553 if (connector->encoder) 1554 if (connector->encoder)
1554 out_resp->encoder_id = connector->encoder->base.id; 1555 out_resp->encoder_id = connector->encoder->base.id;
1555 else 1556 else
1556 out_resp->encoder_id = 0; 1557 out_resp->encoder_id = 0;
1557 1558
1558 /* 1559 /*
1559 * This ioctl is called twice, once to determine how much space is 1560 * This ioctl is called twice, once to determine how much space is
1560 * needed, and the 2nd time to fill it. 1561 * needed, and the 2nd time to fill it.
1561 */ 1562 */
1562 if ((out_resp->count_modes >= mode_count) && mode_count) { 1563 if ((out_resp->count_modes >= mode_count) && mode_count) {
1563 copied = 0; 1564 copied = 0;
1564 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr; 1565 mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
1565 list_for_each_entry(mode, &connector->modes, head) { 1566 list_for_each_entry(mode, &connector->modes, head) {
1566 drm_crtc_convert_to_umode(&u_mode, mode); 1567 drm_crtc_convert_to_umode(&u_mode, mode);
1567 if (copy_to_user(mode_ptr + copied, 1568 if (copy_to_user(mode_ptr + copied,
1568 &u_mode, sizeof(u_mode))) { 1569 &u_mode, sizeof(u_mode))) {
1569 ret = -EFAULT; 1570 ret = -EFAULT;
1570 goto out; 1571 goto out;
1571 } 1572 }
1572 copied++; 1573 copied++;
1573 } 1574 }
1574 } 1575 }
1575 out_resp->count_modes = mode_count; 1576 out_resp->count_modes = mode_count;
1576 1577
1577 if ((out_resp->count_props >= props_count) && props_count) { 1578 if ((out_resp->count_props >= props_count) && props_count) {
1578 copied = 0; 1579 copied = 0;
1579 prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr); 1580 prop_ptr = (uint32_t __user *)(unsigned long)(out_resp->props_ptr);
1580 prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr); 1581 prop_values = (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr);
1581 for (i = 0; i < connector->properties.count; i++) { 1582 for (i = 0; i < connector->properties.count; i++) {
1582 if (put_user(connector->properties.ids[i], 1583 if (put_user(connector->properties.ids[i],
1583 prop_ptr + copied)) { 1584 prop_ptr + copied)) {
1584 ret = -EFAULT; 1585 ret = -EFAULT;
1585 goto out; 1586 goto out;
1586 } 1587 }
1587 1588
1588 if (put_user(connector->properties.values[i], 1589 if (put_user(connector->properties.values[i],
1589 prop_values + copied)) { 1590 prop_values + copied)) {
1590 ret = -EFAULT; 1591 ret = -EFAULT;
1591 goto out; 1592 goto out;
1592 } 1593 }
1593 copied++; 1594 copied++;
1594 } 1595 }
1595 } 1596 }
1596 out_resp->count_props = props_count; 1597 out_resp->count_props = props_count;
1597 1598
1598 if ((out_resp->count_encoders >= encoders_count) && encoders_count) { 1599 if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
1599 copied = 0; 1600 copied = 0;
1600 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr); 1601 encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
1601 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 1602 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
1602 if (connector->encoder_ids[i] != 0) { 1603 if (connector->encoder_ids[i] != 0) {
1603 if (put_user(connector->encoder_ids[i], 1604 if (put_user(connector->encoder_ids[i],
1604 encoder_ptr + copied)) { 1605 encoder_ptr + copied)) {
1605 ret = -EFAULT; 1606 ret = -EFAULT;
1606 goto out; 1607 goto out;
1607 } 1608 }
1608 copied++; 1609 copied++;
1609 } 1610 }
1610 } 1611 }
1611 } 1612 }
1612 out_resp->count_encoders = encoders_count; 1613 out_resp->count_encoders = encoders_count;
1613 1614
1614 out: 1615 out:
1615 mutex_unlock(&dev->mode_config.mutex); 1616 mutex_unlock(&dev->mode_config.mutex);
1616 1617
1617 return ret; 1618 return ret;
1618 } 1619 }
1619 1620
1620 int drm_mode_getencoder(struct drm_device *dev, void *data, 1621 int drm_mode_getencoder(struct drm_device *dev, void *data,
1621 struct drm_file *file_priv) 1622 struct drm_file *file_priv)
1622 { 1623 {
1623 struct drm_mode_get_encoder *enc_resp = data; 1624 struct drm_mode_get_encoder *enc_resp = data;
1624 struct drm_mode_object *obj; 1625 struct drm_mode_object *obj;
1625 struct drm_encoder *encoder; 1626 struct drm_encoder *encoder;
1626 int ret = 0; 1627 int ret = 0;
1627 1628
1628 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1629 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1629 return -EINVAL; 1630 return -EINVAL;
1630 1631
1631 drm_modeset_lock_all(dev); 1632 drm_modeset_lock_all(dev);
1632 obj = drm_mode_object_find(dev, enc_resp->encoder_id, 1633 obj = drm_mode_object_find(dev, enc_resp->encoder_id,
1633 DRM_MODE_OBJECT_ENCODER); 1634 DRM_MODE_OBJECT_ENCODER);
1634 if (!obj) { 1635 if (!obj) {
1635 ret = -EINVAL; 1636 ret = -EINVAL;
1636 goto out; 1637 goto out;
1637 } 1638 }
1638 encoder = obj_to_encoder(obj); 1639 encoder = obj_to_encoder(obj);
1639 1640
1640 if (encoder->crtc) 1641 if (encoder->crtc)
1641 enc_resp->crtc_id = encoder->crtc->base.id; 1642 enc_resp->crtc_id = encoder->crtc->base.id;
1642 else 1643 else
1643 enc_resp->crtc_id = 0; 1644 enc_resp->crtc_id = 0;
1644 enc_resp->encoder_type = encoder->encoder_type; 1645 enc_resp->encoder_type = encoder->encoder_type;
1645 enc_resp->encoder_id = encoder->base.id; 1646 enc_resp->encoder_id = encoder->base.id;
1646 enc_resp->possible_crtcs = encoder->possible_crtcs; 1647 enc_resp->possible_crtcs = encoder->possible_crtcs;
1647 enc_resp->possible_clones = encoder->possible_clones; 1648 enc_resp->possible_clones = encoder->possible_clones;
1648 1649
1649 out: 1650 out:
1650 drm_modeset_unlock_all(dev); 1651 drm_modeset_unlock_all(dev);
1651 return ret; 1652 return ret;
1652 } 1653 }
1653 1654
1654 /** 1655 /**
1655 * drm_mode_getplane_res - get plane info 1656 * drm_mode_getplane_res - get plane info
1656 * @dev: DRM device 1657 * @dev: DRM device
1657 * @data: ioctl data 1658 * @data: ioctl data
1658 * @file_priv: DRM file info 1659 * @file_priv: DRM file info
1659 * 1660 *
1660 * Return an plane count and set of IDs. 1661 * Return an plane count and set of IDs.
1661 */ 1662 */
1662 int drm_mode_getplane_res(struct drm_device *dev, void *data, 1663 int drm_mode_getplane_res(struct drm_device *dev, void *data,
1663 struct drm_file *file_priv) 1664 struct drm_file *file_priv)
1664 { 1665 {
1665 struct drm_mode_get_plane_res *plane_resp = data; 1666 struct drm_mode_get_plane_res *plane_resp = data;
1666 struct drm_mode_config *config; 1667 struct drm_mode_config *config;
1667 struct drm_plane *plane; 1668 struct drm_plane *plane;
1668 uint32_t __user *plane_ptr; 1669 uint32_t __user *plane_ptr;
1669 int copied = 0, ret = 0; 1670 int copied = 0, ret = 0;
1670 1671
1671 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1672 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1672 return -EINVAL; 1673 return -EINVAL;
1673 1674
1674 drm_modeset_lock_all(dev); 1675 drm_modeset_lock_all(dev);
1675 config = &dev->mode_config; 1676 config = &dev->mode_config;
1676 1677
1677 /* 1678 /*
1678 * This ioctl is called twice, once to determine how much space is 1679 * This ioctl is called twice, once to determine how much space is
1679 * needed, and the 2nd time to fill it. 1680 * needed, and the 2nd time to fill it.
1680 */ 1681 */
1681 if (config->num_plane && 1682 if (config->num_plane &&
1682 (plane_resp->count_planes >= config->num_plane)) { 1683 (plane_resp->count_planes >= config->num_plane)) {
1683 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; 1684 plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
1684 1685
1685 list_for_each_entry(plane, &config->plane_list, head) { 1686 list_for_each_entry(plane, &config->plane_list, head) {
1686 if (put_user(plane->base.id, plane_ptr + copied)) { 1687 if (put_user(plane->base.id, plane_ptr + copied)) {
1687 ret = -EFAULT; 1688 ret = -EFAULT;
1688 goto out; 1689 goto out;
1689 } 1690 }
1690 copied++; 1691 copied++;
1691 } 1692 }
1692 } 1693 }
1693 plane_resp->count_planes = config->num_plane; 1694 plane_resp->count_planes = config->num_plane;
1694 1695
1695 out: 1696 out:
1696 drm_modeset_unlock_all(dev); 1697 drm_modeset_unlock_all(dev);
1697 return ret; 1698 return ret;
1698 } 1699 }
1699 1700
1700 /** 1701 /**
1701 * drm_mode_getplane - get plane info 1702 * drm_mode_getplane - get plane info
1702 * @dev: DRM device 1703 * @dev: DRM device
1703 * @data: ioctl data 1704 * @data: ioctl data
1704 * @file_priv: DRM file info 1705 * @file_priv: DRM file info
1705 * 1706 *
1706 * Return plane info, including formats supported, gamma size, any 1707 * Return plane info, including formats supported, gamma size, any
1707 * current fb, etc. 1708 * current fb, etc.
1708 */ 1709 */
1709 int drm_mode_getplane(struct drm_device *dev, void *data, 1710 int drm_mode_getplane(struct drm_device *dev, void *data,
1710 struct drm_file *file_priv) 1711 struct drm_file *file_priv)
1711 { 1712 {
1712 struct drm_mode_get_plane *plane_resp = data; 1713 struct drm_mode_get_plane *plane_resp = data;
1713 struct drm_mode_object *obj; 1714 struct drm_mode_object *obj;
1714 struct drm_plane *plane; 1715 struct drm_plane *plane;
1715 uint32_t __user *format_ptr; 1716 uint32_t __user *format_ptr;
1716 int ret = 0; 1717 int ret = 0;
1717 1718
1718 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1719 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1719 return -EINVAL; 1720 return -EINVAL;
1720 1721
1721 drm_modeset_lock_all(dev); 1722 drm_modeset_lock_all(dev);
1722 obj = drm_mode_object_find(dev, plane_resp->plane_id, 1723 obj = drm_mode_object_find(dev, plane_resp->plane_id,
1723 DRM_MODE_OBJECT_PLANE); 1724 DRM_MODE_OBJECT_PLANE);
1724 if (!obj) { 1725 if (!obj) {
1725 ret = -ENOENT; 1726 ret = -ENOENT;
1726 goto out; 1727 goto out;
1727 } 1728 }
1728 plane = obj_to_plane(obj); 1729 plane = obj_to_plane(obj);
1729 1730
1730 if (plane->crtc) 1731 if (plane->crtc)
1731 plane_resp->crtc_id = plane->crtc->base.id; 1732 plane_resp->crtc_id = plane->crtc->base.id;
1732 else 1733 else
1733 plane_resp->crtc_id = 0; 1734 plane_resp->crtc_id = 0;
1734 1735
1735 if (plane->fb) 1736 if (plane->fb)
1736 plane_resp->fb_id = plane->fb->base.id; 1737 plane_resp->fb_id = plane->fb->base.id;
1737 else 1738 else
1738 plane_resp->fb_id = 0; 1739 plane_resp->fb_id = 0;
1739 1740
1740 plane_resp->plane_id = plane->base.id; 1741 plane_resp->plane_id = plane->base.id;
1741 plane_resp->possible_crtcs = plane->possible_crtcs; 1742 plane_resp->possible_crtcs = plane->possible_crtcs;
1742 plane_resp->gamma_size = plane->gamma_size; 1743 plane_resp->gamma_size = plane->gamma_size;
1743 1744
1744 /* 1745 /*
1745 * This ioctl is called twice, once to determine how much space is 1746 * This ioctl is called twice, once to determine how much space is
1746 * needed, and the 2nd time to fill it. 1747 * needed, and the 2nd time to fill it.
1747 */ 1748 */
1748 if (plane->format_count && 1749 if (plane->format_count &&
1749 (plane_resp->count_format_types >= plane->format_count)) { 1750 (plane_resp->count_format_types >= plane->format_count)) {
1750 format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr; 1751 format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
1751 if (copy_to_user(format_ptr, 1752 if (copy_to_user(format_ptr,
1752 plane->format_types, 1753 plane->format_types,
1753 sizeof(uint32_t) * plane->format_count)) { 1754 sizeof(uint32_t) * plane->format_count)) {
1754 ret = -EFAULT; 1755 ret = -EFAULT;
1755 goto out; 1756 goto out;
1756 } 1757 }
1757 } 1758 }
1758 plane_resp->count_format_types = plane->format_count; 1759 plane_resp->count_format_types = plane->format_count;
1759 1760
1760 out: 1761 out:
1761 drm_modeset_unlock_all(dev); 1762 drm_modeset_unlock_all(dev);
1762 return ret; 1763 return ret;
1763 } 1764 }
1764 1765
1765 /** 1766 /**
1766 * drm_mode_setplane - set up or tear down an plane 1767 * drm_mode_setplane - set up or tear down an plane
1767 * @dev: DRM device 1768 * @dev: DRM device
1768 * @data: ioctl data* 1769 * @data: ioctl data*
1769 * @file_priv: DRM file info 1770 * @file_priv: DRM file info
1770 * 1771 *
1771 * Set plane info, including placement, fb, scaling, and other factors. 1772 * Set plane info, including placement, fb, scaling, and other factors.
1772 * Or pass a NULL fb to disable. 1773 * Or pass a NULL fb to disable.
1773 */ 1774 */
1774 int drm_mode_setplane(struct drm_device *dev, void *data, 1775 int drm_mode_setplane(struct drm_device *dev, void *data,
1775 struct drm_file *file_priv) 1776 struct drm_file *file_priv)
1776 { 1777 {
1777 struct drm_mode_set_plane *plane_req = data; 1778 struct drm_mode_set_plane *plane_req = data;
1778 struct drm_mode_object *obj; 1779 struct drm_mode_object *obj;
1779 struct drm_plane *plane; 1780 struct drm_plane *plane;
1780 struct drm_crtc *crtc; 1781 struct drm_crtc *crtc;
1781 struct drm_framebuffer *fb = NULL, *old_fb = NULL; 1782 struct drm_framebuffer *fb = NULL, *old_fb = NULL;
1782 int ret = 0; 1783 int ret = 0;
1783 unsigned int fb_width, fb_height; 1784 unsigned int fb_width, fb_height;
1784 int i; 1785 int i;
1785 1786
1786 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1787 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1787 return -EINVAL; 1788 return -EINVAL;
1788 1789
1789 /* 1790 /*
1790 * First, find the plane, crtc, and fb objects. If not available, 1791 * First, find the plane, crtc, and fb objects. If not available,
1791 * we don't bother to call the driver. 1792 * we don't bother to call the driver.
1792 */ 1793 */
1793 obj = drm_mode_object_find(dev, plane_req->plane_id, 1794 obj = drm_mode_object_find(dev, plane_req->plane_id,
1794 DRM_MODE_OBJECT_PLANE); 1795 DRM_MODE_OBJECT_PLANE);
1795 if (!obj) { 1796 if (!obj) {
1796 DRM_DEBUG_KMS("Unknown plane ID %d\n", 1797 DRM_DEBUG_KMS("Unknown plane ID %d\n",
1797 plane_req->plane_id); 1798 plane_req->plane_id);
1798 return -ENOENT; 1799 return -ENOENT;
1799 } 1800 }
1800 plane = obj_to_plane(obj); 1801 plane = obj_to_plane(obj);
1801 1802
1802 /* No fb means shut it down */ 1803 /* No fb means shut it down */
1803 if (!plane_req->fb_id) { 1804 if (!plane_req->fb_id) {
1804 drm_modeset_lock_all(dev); 1805 drm_modeset_lock_all(dev);
1805 old_fb = plane->fb; 1806 old_fb = plane->fb;
1806 plane->funcs->disable_plane(plane); 1807 plane->funcs->disable_plane(plane);
1807 plane->crtc = NULL; 1808 plane->crtc = NULL;
1808 plane->fb = NULL; 1809 plane->fb = NULL;
1809 drm_modeset_unlock_all(dev); 1810 drm_modeset_unlock_all(dev);
1810 goto out; 1811 goto out;
1811 } 1812 }
1812 1813
1813 obj = drm_mode_object_find(dev, plane_req->crtc_id, 1814 obj = drm_mode_object_find(dev, plane_req->crtc_id,
1814 DRM_MODE_OBJECT_CRTC); 1815 DRM_MODE_OBJECT_CRTC);
1815 if (!obj) { 1816 if (!obj) {
1816 DRM_DEBUG_KMS("Unknown crtc ID %d\n", 1817 DRM_DEBUG_KMS("Unknown crtc ID %d\n",
1817 plane_req->crtc_id); 1818 plane_req->crtc_id);
1818 ret = -ENOENT; 1819 ret = -ENOENT;
1819 goto out; 1820 goto out;
1820 } 1821 }
1821 crtc = obj_to_crtc(obj); 1822 crtc = obj_to_crtc(obj);
1822 1823
1823 fb = drm_framebuffer_lookup(dev, plane_req->fb_id); 1824 fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
1824 if (!fb) { 1825 if (!fb) {
1825 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", 1826 DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
1826 plane_req->fb_id); 1827 plane_req->fb_id);
1827 ret = -ENOENT; 1828 ret = -ENOENT;
1828 goto out; 1829 goto out;
1829 } 1830 }
1830 1831
1831 /* Check whether this plane supports the fb pixel format. */ 1832 /* Check whether this plane supports the fb pixel format. */
1832 for (i = 0; i < plane->format_count; i++) 1833 for (i = 0; i < plane->format_count; i++)
1833 if (fb->pixel_format == plane->format_types[i]) 1834 if (fb->pixel_format == plane->format_types[i])
1834 break; 1835 break;
1835 if (i == plane->format_count) { 1836 if (i == plane->format_count) {
1836 DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format); 1837 DRM_DEBUG_KMS("Invalid pixel format 0x%08x\n", fb->pixel_format);
1837 ret = -EINVAL; 1838 ret = -EINVAL;
1838 goto out; 1839 goto out;
1839 } 1840 }
1840 1841
1841 fb_width = fb->width << 16; 1842 fb_width = fb->width << 16;
1842 fb_height = fb->height << 16; 1843 fb_height = fb->height << 16;
1843 1844
1844 /* Make sure source coordinates are inside the fb. */ 1845 /* Make sure source coordinates are inside the fb. */
1845 if (plane_req->src_w > fb_width || 1846 if (plane_req->src_w > fb_width ||
1846 plane_req->src_x > fb_width - plane_req->src_w || 1847 plane_req->src_x > fb_width - plane_req->src_w ||
1847 plane_req->src_h > fb_height || 1848 plane_req->src_h > fb_height ||
1848 plane_req->src_y > fb_height - plane_req->src_h) { 1849 plane_req->src_y > fb_height - plane_req->src_h) {
1849 DRM_DEBUG_KMS("Invalid source coordinates " 1850 DRM_DEBUG_KMS("Invalid source coordinates "
1850 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n", 1851 "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
1851 plane_req->src_w >> 16, 1852 plane_req->src_w >> 16,
1852 ((plane_req->src_w & 0xffff) * 15625) >> 10, 1853 ((plane_req->src_w & 0xffff) * 15625) >> 10,
1853 plane_req->src_h >> 16, 1854 plane_req->src_h >> 16,
1854 ((plane_req->src_h & 0xffff) * 15625) >> 10, 1855 ((plane_req->src_h & 0xffff) * 15625) >> 10,
1855 plane_req->src_x >> 16, 1856 plane_req->src_x >> 16,
1856 ((plane_req->src_x & 0xffff) * 15625) >> 10, 1857 ((plane_req->src_x & 0xffff) * 15625) >> 10,
1857 plane_req->src_y >> 16, 1858 plane_req->src_y >> 16,
1858 ((plane_req->src_y & 0xffff) * 15625) >> 10); 1859 ((plane_req->src_y & 0xffff) * 15625) >> 10);
1859 ret = -ENOSPC; 1860 ret = -ENOSPC;
1860 goto out; 1861 goto out;
1861 } 1862 }
1862 1863
1863 /* Give drivers some help against integer overflows */ 1864 /* Give drivers some help against integer overflows */
1864 if (plane_req->crtc_w > INT_MAX || 1865 if (plane_req->crtc_w > INT_MAX ||
1865 plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w || 1866 plane_req->crtc_x > INT_MAX - (int32_t) plane_req->crtc_w ||
1866 plane_req->crtc_h > INT_MAX || 1867 plane_req->crtc_h > INT_MAX ||
1867 plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) { 1868 plane_req->crtc_y > INT_MAX - (int32_t) plane_req->crtc_h) {
1868 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n", 1869 DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
1869 plane_req->crtc_w, plane_req->crtc_h, 1870 plane_req->crtc_w, plane_req->crtc_h,
1870 plane_req->crtc_x, plane_req->crtc_y); 1871 plane_req->crtc_x, plane_req->crtc_y);
1871 ret = -ERANGE; 1872 ret = -ERANGE;
1872 goto out; 1873 goto out;
1873 } 1874 }
1874 1875
1875 drm_modeset_lock_all(dev); 1876 drm_modeset_lock_all(dev);
1876 ret = plane->funcs->update_plane(plane, crtc, fb, 1877 ret = plane->funcs->update_plane(plane, crtc, fb,
1877 plane_req->crtc_x, plane_req->crtc_y, 1878 plane_req->crtc_x, plane_req->crtc_y,
1878 plane_req->crtc_w, plane_req->crtc_h, 1879 plane_req->crtc_w, plane_req->crtc_h,
1879 plane_req->src_x, plane_req->src_y, 1880 plane_req->src_x, plane_req->src_y,
1880 plane_req->src_w, plane_req->src_h); 1881 plane_req->src_w, plane_req->src_h);
1881 if (!ret) { 1882 if (!ret) {
1882 old_fb = plane->fb; 1883 old_fb = plane->fb;
1883 plane->crtc = crtc; 1884 plane->crtc = crtc;
1884 plane->fb = fb; 1885 plane->fb = fb;
1885 fb = NULL; 1886 fb = NULL;
1886 } 1887 }
1887 drm_modeset_unlock_all(dev); 1888 drm_modeset_unlock_all(dev);
1888 1889
1889 out: 1890 out:
1890 if (fb) 1891 if (fb)
1891 drm_framebuffer_unreference(fb); 1892 drm_framebuffer_unreference(fb);
1892 if (old_fb) 1893 if (old_fb)
1893 drm_framebuffer_unreference(old_fb); 1894 drm_framebuffer_unreference(old_fb);
1894 1895
1895 return ret; 1896 return ret;
1896 } 1897 }
1897 1898
1898 /** 1899 /**
1899 * drm_mode_set_config_internal - helper to call ->set_config 1900 * drm_mode_set_config_internal - helper to call ->set_config
1900 * @set: modeset config to set 1901 * @set: modeset config to set
1901 * 1902 *
1902 * This is a little helper to wrap internal calls to the ->set_config driver 1903 * This is a little helper to wrap internal calls to the ->set_config driver
1903 * interface. The only thing it adds is correct refcounting dance. 1904 * interface. The only thing it adds is correct refcounting dance.
1904 */ 1905 */
1905 int drm_mode_set_config_internal(struct drm_mode_set *set) 1906 int drm_mode_set_config_internal(struct drm_mode_set *set)
1906 { 1907 {
1907 struct drm_crtc *crtc = set->crtc; 1908 struct drm_crtc *crtc = set->crtc;
1908 struct drm_framebuffer *fb, *old_fb; 1909 struct drm_framebuffer *fb, *old_fb;
1909 int ret; 1910 int ret;
1910 1911
1911 old_fb = crtc->fb; 1912 old_fb = crtc->fb;
1912 fb = set->fb; 1913 fb = set->fb;
1913 1914
1914 ret = crtc->funcs->set_config(set); 1915 ret = crtc->funcs->set_config(set);
1915 if (ret == 0) { 1916 if (ret == 0) {
1916 if (old_fb) 1917 if (old_fb)
1917 drm_framebuffer_unreference(old_fb); 1918 drm_framebuffer_unreference(old_fb);
1918 if (fb) 1919 if (fb)
1919 drm_framebuffer_reference(fb); 1920 drm_framebuffer_reference(fb);
1920 } 1921 }
1921 1922
1922 return ret; 1923 return ret;
1923 } 1924 }
1924 EXPORT_SYMBOL(drm_mode_set_config_internal); 1925 EXPORT_SYMBOL(drm_mode_set_config_internal);
1925 1926
1926 /** 1927 /**
1927 * drm_mode_setcrtc - set CRTC configuration 1928 * drm_mode_setcrtc - set CRTC configuration
1928 * @dev: drm device for the ioctl 1929 * @dev: drm device for the ioctl
1929 * @data: data pointer for the ioctl 1930 * @data: data pointer for the ioctl
1930 * @file_priv: drm file for the ioctl call 1931 * @file_priv: drm file for the ioctl call
1931 * 1932 *
1932 * Build a new CRTC configuration based on user request. 1933 * Build a new CRTC configuration based on user request.
1933 * 1934 *
1934 * Called by the user via ioctl. 1935 * Called by the user via ioctl.
1935 * 1936 *
1936 * RETURNS: 1937 * RETURNS:
1937 * Zero on success, errno on failure. 1938 * Zero on success, errno on failure.
1938 */ 1939 */
1939 int drm_mode_setcrtc(struct drm_device *dev, void *data, 1940 int drm_mode_setcrtc(struct drm_device *dev, void *data,
1940 struct drm_file *file_priv) 1941 struct drm_file *file_priv)
1941 { 1942 {
1942 struct drm_mode_config *config = &dev->mode_config; 1943 struct drm_mode_config *config = &dev->mode_config;
1943 struct drm_mode_crtc *crtc_req = data; 1944 struct drm_mode_crtc *crtc_req = data;
1944 struct drm_mode_object *obj; 1945 struct drm_mode_object *obj;
1945 struct drm_crtc *crtc; 1946 struct drm_crtc *crtc;
1946 struct drm_connector **connector_set = NULL, *connector; 1947 struct drm_connector **connector_set = NULL, *connector;
1947 struct drm_framebuffer *fb = NULL; 1948 struct drm_framebuffer *fb = NULL;
1948 struct drm_display_mode *mode = NULL; 1949 struct drm_display_mode *mode = NULL;
1949 struct drm_mode_set set; 1950 struct drm_mode_set set;
1950 uint32_t __user *set_connectors_ptr; 1951 uint32_t __user *set_connectors_ptr;
1951 int ret; 1952 int ret;
1952 int i; 1953 int i;
1953 1954
1954 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 1955 if (!drm_core_check_feature(dev, DRIVER_MODESET))
1955 return -EINVAL; 1956 return -EINVAL;
1956 1957
1957 /* For some reason crtc x/y offsets are signed internally. */ 1958 /* For some reason crtc x/y offsets are signed internally. */
1958 if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX) 1959 if (crtc_req->x > INT_MAX || crtc_req->y > INT_MAX)
1959 return -ERANGE; 1960 return -ERANGE;
1960 1961
1961 drm_modeset_lock_all(dev); 1962 drm_modeset_lock_all(dev);
1962 obj = drm_mode_object_find(dev, crtc_req->crtc_id, 1963 obj = drm_mode_object_find(dev, crtc_req->crtc_id,
1963 DRM_MODE_OBJECT_CRTC); 1964 DRM_MODE_OBJECT_CRTC);
1964 if (!obj) { 1965 if (!obj) {
1965 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); 1966 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
1966 ret = -EINVAL; 1967 ret = -EINVAL;
1967 goto out; 1968 goto out;
1968 } 1969 }
1969 crtc = obj_to_crtc(obj); 1970 crtc = obj_to_crtc(obj);
1970 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 1971 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
1971 1972
1972 if (crtc_req->mode_valid) { 1973 if (crtc_req->mode_valid) {
1973 int hdisplay, vdisplay; 1974 int hdisplay, vdisplay;
1974 /* If we have a mode we need a framebuffer. */ 1975 /* If we have a mode we need a framebuffer. */
1975 /* If we pass -1, set the mode with the currently bound fb */ 1976 /* If we pass -1, set the mode with the currently bound fb */
1976 if (crtc_req->fb_id == -1) { 1977 if (crtc_req->fb_id == -1) {
1977 if (!crtc->fb) { 1978 if (!crtc->fb) {
1978 DRM_DEBUG_KMS("CRTC doesn't have current FB\n"); 1979 DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
1979 ret = -EINVAL; 1980 ret = -EINVAL;
1980 goto out; 1981 goto out;
1981 } 1982 }
1982 fb = crtc->fb; 1983 fb = crtc->fb;
1983 /* Make refcounting symmetric with the lookup path. */ 1984 /* Make refcounting symmetric with the lookup path. */
1984 drm_framebuffer_reference(fb); 1985 drm_framebuffer_reference(fb);
1985 } else { 1986 } else {
1986 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id); 1987 fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
1987 if (!fb) { 1988 if (!fb) {
1988 DRM_DEBUG_KMS("Unknown FB ID%d\n", 1989 DRM_DEBUG_KMS("Unknown FB ID%d\n",
1989 crtc_req->fb_id); 1990 crtc_req->fb_id);
1990 ret = -EINVAL; 1991 ret = -EINVAL;
1991 goto out; 1992 goto out;
1992 } 1993 }
1993 } 1994 }
1994 1995
1995 mode = drm_mode_create(dev); 1996 mode = drm_mode_create(dev);
1996 if (!mode) { 1997 if (!mode) {
1997 ret = -ENOMEM; 1998 ret = -ENOMEM;
1998 goto out; 1999 goto out;
1999 } 2000 }
2000 2001
2001 ret = drm_crtc_convert_umode(mode, &crtc_req->mode); 2002 ret = drm_crtc_convert_umode(mode, &crtc_req->mode);
2002 if (ret) { 2003 if (ret) {
2003 DRM_DEBUG_KMS("Invalid mode\n"); 2004 DRM_DEBUG_KMS("Invalid mode\n");
2004 goto out; 2005 goto out;
2005 } 2006 }
2006 2007
2007 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 2008 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
2008 2009
2009 hdisplay = mode->hdisplay; 2010 hdisplay = mode->hdisplay;
2010 vdisplay = mode->vdisplay; 2011 vdisplay = mode->vdisplay;
2011 2012
2012 if (crtc->invert_dimensions) 2013 if (crtc->invert_dimensions)
2013 swap(hdisplay, vdisplay); 2014 swap(hdisplay, vdisplay);
2014 2015
2015 if (hdisplay > fb->width || 2016 if (hdisplay > fb->width ||
2016 vdisplay > fb->height || 2017 vdisplay > fb->height ||
2017 crtc_req->x > fb->width - hdisplay || 2018 crtc_req->x > fb->width - hdisplay ||
2018 crtc_req->y > fb->height - vdisplay) { 2019 crtc_req->y > fb->height - vdisplay) {
2019 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", 2020 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
2020 fb->width, fb->height, 2021 fb->width, fb->height,
2021 hdisplay, vdisplay, crtc_req->x, crtc_req->y, 2022 hdisplay, vdisplay, crtc_req->x, crtc_req->y,
2022 crtc->invert_dimensions ? " (inverted)" : ""); 2023 crtc->invert_dimensions ? " (inverted)" : "");
2023 ret = -ENOSPC; 2024 ret = -ENOSPC;
2024 goto out; 2025 goto out;
2025 } 2026 }
2026 } 2027 }
2027 2028
2028 if (crtc_req->count_connectors == 0 && mode) { 2029 if (crtc_req->count_connectors == 0 && mode) {
2029 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n"); 2030 DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
2030 ret = -EINVAL; 2031 ret = -EINVAL;
2031 goto out; 2032 goto out;
2032 } 2033 }
2033 2034
2034 if (crtc_req->count_connectors > 0 && (!mode || !fb)) { 2035 if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
2035 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n", 2036 DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
2036 crtc_req->count_connectors); 2037 crtc_req->count_connectors);
2037 ret = -EINVAL; 2038 ret = -EINVAL;
2038 goto out; 2039 goto out;
2039 } 2040 }
2040 2041
2041 if (crtc_req->count_connectors > 0) { 2042 if (crtc_req->count_connectors > 0) {
2042 u32 out_id; 2043 u32 out_id;
2043 2044
2044 /* Avoid unbounded kernel memory allocation */ 2045 /* Avoid unbounded kernel memory allocation */
2045 if (crtc_req->count_connectors > config->num_connector) { 2046 if (crtc_req->count_connectors > config->num_connector) {
2046 ret = -EINVAL; 2047 ret = -EINVAL;
2047 goto out; 2048 goto out;
2048 } 2049 }
2049 2050
2050 connector_set = kmalloc(crtc_req->count_connectors * 2051 connector_set = kmalloc(crtc_req->count_connectors *
2051 sizeof(struct drm_connector *), 2052 sizeof(struct drm_connector *),
2052 GFP_KERNEL); 2053 GFP_KERNEL);
2053 if (!connector_set) { 2054 if (!connector_set) {
2054 ret = -ENOMEM; 2055 ret = -ENOMEM;
2055 goto out; 2056 goto out;
2056 } 2057 }
2057 2058
2058 for (i = 0; i < crtc_req->count_connectors; i++) { 2059 for (i = 0; i < crtc_req->count_connectors; i++) {
2059 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr; 2060 set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
2060 if (get_user(out_id, &set_connectors_ptr[i])) { 2061 if (get_user(out_id, &set_connectors_ptr[i])) {
2061 ret = -EFAULT; 2062 ret = -EFAULT;
2062 goto out; 2063 goto out;
2063 } 2064 }
2064 2065
2065 obj = drm_mode_object_find(dev, out_id, 2066 obj = drm_mode_object_find(dev, out_id,
2066 DRM_MODE_OBJECT_CONNECTOR); 2067 DRM_MODE_OBJECT_CONNECTOR);
2067 if (!obj) { 2068 if (!obj) {
2068 DRM_DEBUG_KMS("Connector id %d unknown\n", 2069 DRM_DEBUG_KMS("Connector id %d unknown\n",
2069 out_id); 2070 out_id);
2070 ret = -EINVAL; 2071 ret = -EINVAL;
2071 goto out; 2072 goto out;
2072 } 2073 }
2073 connector = obj_to_connector(obj); 2074 connector = obj_to_connector(obj);
2074 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", 2075 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
2075 connector->base.id, 2076 connector->base.id,
2076 drm_get_connector_name(connector)); 2077 drm_get_connector_name(connector));
2077 2078
2078 connector_set[i] = connector; 2079 connector_set[i] = connector;
2079 } 2080 }
2080 } 2081 }
2081 2082
2082 set.crtc = crtc; 2083 set.crtc = crtc;
2083 set.x = crtc_req->x; 2084 set.x = crtc_req->x;
2084 set.y = crtc_req->y; 2085 set.y = crtc_req->y;
2085 set.mode = mode; 2086 set.mode = mode;
2086 set.connectors = connector_set; 2087 set.connectors = connector_set;
2087 set.num_connectors = crtc_req->count_connectors; 2088 set.num_connectors = crtc_req->count_connectors;
2088 set.fb = fb; 2089 set.fb = fb;
2089 ret = drm_mode_set_config_internal(&set); 2090 ret = drm_mode_set_config_internal(&set);
2090 2091
2091 out: 2092 out:
2092 if (fb) 2093 if (fb)
2093 drm_framebuffer_unreference(fb); 2094 drm_framebuffer_unreference(fb);
2094 2095
2095 kfree(connector_set); 2096 kfree(connector_set);
2096 drm_mode_destroy(dev, mode); 2097 drm_mode_destroy(dev, mode);
2097 drm_modeset_unlock_all(dev); 2098 drm_modeset_unlock_all(dev);
2098 return ret; 2099 return ret;
2099 } 2100 }
2100 2101
2101 int drm_mode_cursor_ioctl(struct drm_device *dev, 2102 int drm_mode_cursor_ioctl(struct drm_device *dev,
2102 void *data, struct drm_file *file_priv) 2103 void *data, struct drm_file *file_priv)
2103 { 2104 {
2104 struct drm_mode_cursor *req = data; 2105 struct drm_mode_cursor *req = data;
2105 struct drm_mode_object *obj; 2106 struct drm_mode_object *obj;
2106 struct drm_crtc *crtc; 2107 struct drm_crtc *crtc;
2107 int ret = 0; 2108 int ret = 0;
2108 2109
2109 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2110 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2110 return -EINVAL; 2111 return -EINVAL;
2111 2112
2112 if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) 2113 if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
2113 return -EINVAL; 2114 return -EINVAL;
2114 2115
2115 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC); 2116 obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
2116 if (!obj) { 2117 if (!obj) {
2117 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); 2118 DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
2118 return -EINVAL; 2119 return -EINVAL;
2119 } 2120 }
2120 crtc = obj_to_crtc(obj); 2121 crtc = obj_to_crtc(obj);
2121 2122
2122 mutex_lock(&crtc->mutex); 2123 mutex_lock(&crtc->mutex);
2123 if (req->flags & DRM_MODE_CURSOR_BO) { 2124 if (req->flags & DRM_MODE_CURSOR_BO) {
2124 if (!crtc->funcs->cursor_set) { 2125 if (!crtc->funcs->cursor_set) {
2125 ret = -ENXIO; 2126 ret = -ENXIO;
2126 goto out; 2127 goto out;
2127 } 2128 }
2128 /* Turns off the cursor if handle is 0 */ 2129 /* Turns off the cursor if handle is 0 */
2129 ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle, 2130 ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
2130 req->width, req->height); 2131 req->width, req->height);
2131 } 2132 }
2132 2133
2133 if (req->flags & DRM_MODE_CURSOR_MOVE) { 2134 if (req->flags & DRM_MODE_CURSOR_MOVE) {
2134 if (crtc->funcs->cursor_move) { 2135 if (crtc->funcs->cursor_move) {
2135 ret = crtc->funcs->cursor_move(crtc, req->x, req->y); 2136 ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
2136 } else { 2137 } else {
2137 ret = -EFAULT; 2138 ret = -EFAULT;
2138 goto out; 2139 goto out;
2139 } 2140 }
2140 } 2141 }
2141 out: 2142 out:
2142 mutex_unlock(&crtc->mutex); 2143 mutex_unlock(&crtc->mutex);
2143 2144
2144 return ret; 2145 return ret;
2145 } 2146 }
2146 2147
2147 /* Original addfb only supported RGB formats, so figure out which one */ 2148 /* Original addfb only supported RGB formats, so figure out which one */
2148 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) 2149 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
2149 { 2150 {
2150 uint32_t fmt; 2151 uint32_t fmt;
2151 2152
2152 switch (bpp) { 2153 switch (bpp) {
2153 case 8: 2154 case 8:
2154 fmt = DRM_FORMAT_C8; 2155 fmt = DRM_FORMAT_C8;
2155 break; 2156 break;
2156 case 16: 2157 case 16:
2157 if (depth == 15) 2158 if (depth == 15)
2158 fmt = DRM_FORMAT_XRGB1555; 2159 fmt = DRM_FORMAT_XRGB1555;
2159 else 2160 else
2160 fmt = DRM_FORMAT_RGB565; 2161 fmt = DRM_FORMAT_RGB565;
2161 break; 2162 break;
2162 case 24: 2163 case 24:
2163 fmt = DRM_FORMAT_RGB888; 2164 fmt = DRM_FORMAT_RGB888;
2164 break; 2165 break;
2165 case 32: 2166 case 32:
2166 if (depth == 24) 2167 if (depth == 24)
2167 fmt = DRM_FORMAT_XRGB8888; 2168 fmt = DRM_FORMAT_XRGB8888;
2168 else if (depth == 30) 2169 else if (depth == 30)
2169 fmt = DRM_FORMAT_XRGB2101010; 2170 fmt = DRM_FORMAT_XRGB2101010;
2170 else 2171 else
2171 fmt = DRM_FORMAT_ARGB8888; 2172 fmt = DRM_FORMAT_ARGB8888;
2172 break; 2173 break;
2173 default: 2174 default:
2174 DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n"); 2175 DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
2175 fmt = DRM_FORMAT_XRGB8888; 2176 fmt = DRM_FORMAT_XRGB8888;
2176 break; 2177 break;
2177 } 2178 }
2178 2179
2179 return fmt; 2180 return fmt;
2180 } 2181 }
2181 EXPORT_SYMBOL(drm_mode_legacy_fb_format); 2182 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
2182 2183
2183 /** 2184 /**
2184 * drm_mode_addfb - add an FB to the graphics configuration 2185 * drm_mode_addfb - add an FB to the graphics configuration
2185 * @dev: drm device for the ioctl 2186 * @dev: drm device for the ioctl
2186 * @data: data pointer for the ioctl 2187 * @data: data pointer for the ioctl
2187 * @file_priv: drm file for the ioctl call 2188 * @file_priv: drm file for the ioctl call
2188 * 2189 *
2189 * Add a new FB to the specified CRTC, given a user request. 2190 * Add a new FB to the specified CRTC, given a user request.
2190 * 2191 *
2191 * Called by the user via ioctl. 2192 * Called by the user via ioctl.
2192 * 2193 *
2193 * RETURNS: 2194 * RETURNS:
2194 * Zero on success, errno on failure. 2195 * Zero on success, errno on failure.
2195 */ 2196 */
2196 int drm_mode_addfb(struct drm_device *dev, 2197 int drm_mode_addfb(struct drm_device *dev,
2197 void *data, struct drm_file *file_priv) 2198 void *data, struct drm_file *file_priv)
2198 { 2199 {
2199 struct drm_mode_fb_cmd *or = data; 2200 struct drm_mode_fb_cmd *or = data;
2200 struct drm_mode_fb_cmd2 r = {}; 2201 struct drm_mode_fb_cmd2 r = {};
2201 struct drm_mode_config *config = &dev->mode_config; 2202 struct drm_mode_config *config = &dev->mode_config;
2202 struct drm_framebuffer *fb; 2203 struct drm_framebuffer *fb;
2203 int ret = 0; 2204 int ret = 0;
2204 2205
2205 /* Use new struct with format internally */ 2206 /* Use new struct with format internally */
2206 r.fb_id = or->fb_id; 2207 r.fb_id = or->fb_id;
2207 r.width = or->width; 2208 r.width = or->width;
2208 r.height = or->height; 2209 r.height = or->height;
2209 r.pitches[0] = or->pitch; 2210 r.pitches[0] = or->pitch;
2210 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth); 2211 r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
2211 r.handles[0] = or->handle; 2212 r.handles[0] = or->handle;
2212 2213
2213 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2214 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2214 return -EINVAL; 2215 return -EINVAL;
2215 2216
2216 if ((config->min_width > r.width) || (r.width > config->max_width)) 2217 if ((config->min_width > r.width) || (r.width > config->max_width))
2217 return -EINVAL; 2218 return -EINVAL;
2218 2219
2219 if ((config->min_height > r.height) || (r.height > config->max_height)) 2220 if ((config->min_height > r.height) || (r.height > config->max_height))
2220 return -EINVAL; 2221 return -EINVAL;
2221 2222
2222 fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r); 2223 fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
2223 if (IS_ERR(fb)) { 2224 if (IS_ERR(fb)) {
2224 DRM_DEBUG_KMS("could not create framebuffer\n"); 2225 DRM_DEBUG_KMS("could not create framebuffer\n");
2225 return PTR_ERR(fb); 2226 return PTR_ERR(fb);
2226 } 2227 }
2227 2228
2228 mutex_lock(&file_priv->fbs_lock); 2229 mutex_lock(&file_priv->fbs_lock);
2229 or->fb_id = fb->base.id; 2230 or->fb_id = fb->base.id;
2230 list_add(&fb->filp_head, &file_priv->fbs); 2231 list_add(&fb->filp_head, &file_priv->fbs);
2231 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2232 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2232 mutex_unlock(&file_priv->fbs_lock); 2233 mutex_unlock(&file_priv->fbs_lock);
2233 2234
2234 return ret; 2235 return ret;
2235 } 2236 }
2236 2237
2237 static int format_check(const struct drm_mode_fb_cmd2 *r) 2238 static int format_check(const struct drm_mode_fb_cmd2 *r)
2238 { 2239 {
2239 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN; 2240 uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
2240 2241
2241 switch (format) { 2242 switch (format) {
2242 case DRM_FORMAT_C8: 2243 case DRM_FORMAT_C8:
2243 case DRM_FORMAT_RGB332: 2244 case DRM_FORMAT_RGB332:
2244 case DRM_FORMAT_BGR233: 2245 case DRM_FORMAT_BGR233:
2245 case DRM_FORMAT_XRGB4444: 2246 case DRM_FORMAT_XRGB4444:
2246 case DRM_FORMAT_XBGR4444: 2247 case DRM_FORMAT_XBGR4444:
2247 case DRM_FORMAT_RGBX4444: 2248 case DRM_FORMAT_RGBX4444:
2248 case DRM_FORMAT_BGRX4444: 2249 case DRM_FORMAT_BGRX4444:
2249 case DRM_FORMAT_ARGB4444: 2250 case DRM_FORMAT_ARGB4444:
2250 case DRM_FORMAT_ABGR4444: 2251 case DRM_FORMAT_ABGR4444:
2251 case DRM_FORMAT_RGBA4444: 2252 case DRM_FORMAT_RGBA4444:
2252 case DRM_FORMAT_BGRA4444: 2253 case DRM_FORMAT_BGRA4444:
2253 case DRM_FORMAT_XRGB1555: 2254 case DRM_FORMAT_XRGB1555:
2254 case DRM_FORMAT_XBGR1555: 2255 case DRM_FORMAT_XBGR1555:
2255 case DRM_FORMAT_RGBX5551: 2256 case DRM_FORMAT_RGBX5551:
2256 case DRM_FORMAT_BGRX5551: 2257 case DRM_FORMAT_BGRX5551:
2257 case DRM_FORMAT_ARGB1555: 2258 case DRM_FORMAT_ARGB1555:
2258 case DRM_FORMAT_ABGR1555: 2259 case DRM_FORMAT_ABGR1555:
2259 case DRM_FORMAT_RGBA5551: 2260 case DRM_FORMAT_RGBA5551:
2260 case DRM_FORMAT_BGRA5551: 2261 case DRM_FORMAT_BGRA5551:
2261 case DRM_FORMAT_RGB565: 2262 case DRM_FORMAT_RGB565:
2262 case DRM_FORMAT_BGR565: 2263 case DRM_FORMAT_BGR565:
2263 case DRM_FORMAT_RGB888: 2264 case DRM_FORMAT_RGB888:
2264 case DRM_FORMAT_BGR888: 2265 case DRM_FORMAT_BGR888:
2265 case DRM_FORMAT_XRGB8888: 2266 case DRM_FORMAT_XRGB8888:
2266 case DRM_FORMAT_XBGR8888: 2267 case DRM_FORMAT_XBGR8888:
2267 case DRM_FORMAT_RGBX8888: 2268 case DRM_FORMAT_RGBX8888:
2268 case DRM_FORMAT_BGRX8888: 2269 case DRM_FORMAT_BGRX8888:
2269 case DRM_FORMAT_ARGB8888: 2270 case DRM_FORMAT_ARGB8888:
2270 case DRM_FORMAT_ABGR8888: 2271 case DRM_FORMAT_ABGR8888:
2271 case DRM_FORMAT_RGBA8888: 2272 case DRM_FORMAT_RGBA8888:
2272 case DRM_FORMAT_BGRA8888: 2273 case DRM_FORMAT_BGRA8888:
2273 case DRM_FORMAT_XRGB2101010: 2274 case DRM_FORMAT_XRGB2101010:
2274 case DRM_FORMAT_XBGR2101010: 2275 case DRM_FORMAT_XBGR2101010:
2275 case DRM_FORMAT_RGBX1010102: 2276 case DRM_FORMAT_RGBX1010102:
2276 case DRM_FORMAT_BGRX1010102: 2277 case DRM_FORMAT_BGRX1010102:
2277 case DRM_FORMAT_ARGB2101010: 2278 case DRM_FORMAT_ARGB2101010:
2278 case DRM_FORMAT_ABGR2101010: 2279 case DRM_FORMAT_ABGR2101010:
2279 case DRM_FORMAT_RGBA1010102: 2280 case DRM_FORMAT_RGBA1010102:
2280 case DRM_FORMAT_BGRA1010102: 2281 case DRM_FORMAT_BGRA1010102:
2281 case DRM_FORMAT_YUYV: 2282 case DRM_FORMAT_YUYV:
2282 case DRM_FORMAT_YVYU: 2283 case DRM_FORMAT_YVYU:
2283 case DRM_FORMAT_UYVY: 2284 case DRM_FORMAT_UYVY:
2284 case DRM_FORMAT_VYUY: 2285 case DRM_FORMAT_VYUY:
2285 case DRM_FORMAT_AYUV: 2286 case DRM_FORMAT_AYUV:
2286 case DRM_FORMAT_NV12: 2287 case DRM_FORMAT_NV12:
2287 case DRM_FORMAT_NV21: 2288 case DRM_FORMAT_NV21:
2288 case DRM_FORMAT_NV16: 2289 case DRM_FORMAT_NV16:
2289 case DRM_FORMAT_NV61: 2290 case DRM_FORMAT_NV61:
2290 case DRM_FORMAT_NV24: 2291 case DRM_FORMAT_NV24:
2291 case DRM_FORMAT_NV42: 2292 case DRM_FORMAT_NV42:
2292 case DRM_FORMAT_YUV410: 2293 case DRM_FORMAT_YUV410:
2293 case DRM_FORMAT_YVU410: 2294 case DRM_FORMAT_YVU410:
2294 case DRM_FORMAT_YUV411: 2295 case DRM_FORMAT_YUV411:
2295 case DRM_FORMAT_YVU411: 2296 case DRM_FORMAT_YVU411:
2296 case DRM_FORMAT_YUV420: 2297 case DRM_FORMAT_YUV420:
2297 case DRM_FORMAT_YVU420: 2298 case DRM_FORMAT_YVU420:
2298 case DRM_FORMAT_YUV422: 2299 case DRM_FORMAT_YUV422:
2299 case DRM_FORMAT_YVU422: 2300 case DRM_FORMAT_YVU422:
2300 case DRM_FORMAT_YUV444: 2301 case DRM_FORMAT_YUV444:
2301 case DRM_FORMAT_YVU444: 2302 case DRM_FORMAT_YVU444:
2302 return 0; 2303 return 0;
2303 default: 2304 default:
2304 return -EINVAL; 2305 return -EINVAL;
2305 } 2306 }
2306 } 2307 }
2307 2308
2308 static int framebuffer_check(const struct drm_mode_fb_cmd2 *r) 2309 static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
2309 { 2310 {
2310 int ret, hsub, vsub, num_planes, i; 2311 int ret, hsub, vsub, num_planes, i;
2311 2312
2312 ret = format_check(r); 2313 ret = format_check(r);
2313 if (ret) { 2314 if (ret) {
2314 DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format); 2315 DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
2315 return ret; 2316 return ret;
2316 } 2317 }
2317 2318
2318 hsub = drm_format_horz_chroma_subsampling(r->pixel_format); 2319 hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
2319 vsub = drm_format_vert_chroma_subsampling(r->pixel_format); 2320 vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
2320 num_planes = drm_format_num_planes(r->pixel_format); 2321 num_planes = drm_format_num_planes(r->pixel_format);
2321 2322
2322 if (r->width == 0 || r->width % hsub) { 2323 if (r->width == 0 || r->width % hsub) {
2323 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height); 2324 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
2324 return -EINVAL; 2325 return -EINVAL;
2325 } 2326 }
2326 2327
2327 if (r->height == 0 || r->height % vsub) { 2328 if (r->height == 0 || r->height % vsub) {
2328 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height); 2329 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
2329 return -EINVAL; 2330 return -EINVAL;
2330 } 2331 }
2331 2332
2332 for (i = 0; i < num_planes; i++) { 2333 for (i = 0; i < num_planes; i++) {
2333 unsigned int width = r->width / (i != 0 ? hsub : 1); 2334 unsigned int width = r->width / (i != 0 ? hsub : 1);
2334 unsigned int height = r->height / (i != 0 ? vsub : 1); 2335 unsigned int height = r->height / (i != 0 ? vsub : 1);
2335 unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i); 2336 unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
2336 2337
2337 if (!r->handles[i]) { 2338 if (!r->handles[i]) {
2338 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i); 2339 DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
2339 return -EINVAL; 2340 return -EINVAL;
2340 } 2341 }
2341 2342
2342 if ((uint64_t) width * cpp > UINT_MAX) 2343 if ((uint64_t) width * cpp > UINT_MAX)
2343 return -ERANGE; 2344 return -ERANGE;
2344 2345
2345 if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX) 2346 if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
2346 return -ERANGE; 2347 return -ERANGE;
2347 2348
2348 if (r->pitches[i] < width * cpp) { 2349 if (r->pitches[i] < width * cpp) {
2349 DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i); 2350 DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
2350 return -EINVAL; 2351 return -EINVAL;
2351 } 2352 }
2352 } 2353 }
2353 2354
2354 return 0; 2355 return 0;
2355 } 2356 }
2356 2357
2357 /** 2358 /**
2358 * drm_mode_addfb2 - add an FB to the graphics configuration 2359 * drm_mode_addfb2 - add an FB to the graphics configuration
2359 * @dev: drm device for the ioctl 2360 * @dev: drm device for the ioctl
2360 * @data: data pointer for the ioctl 2361 * @data: data pointer for the ioctl
2361 * @file_priv: drm file for the ioctl call 2362 * @file_priv: drm file for the ioctl call
2362 * 2363 *
2363 * Add a new FB to the specified CRTC, given a user request with format. 2364 * Add a new FB to the specified CRTC, given a user request with format.
2364 * 2365 *
2365 * Called by the user via ioctl. 2366 * Called by the user via ioctl.
2366 * 2367 *
2367 * RETURNS: 2368 * RETURNS:
2368 * Zero on success, errno on failure. 2369 * Zero on success, errno on failure.
2369 */ 2370 */
2370 int drm_mode_addfb2(struct drm_device *dev, 2371 int drm_mode_addfb2(struct drm_device *dev,
2371 void *data, struct drm_file *file_priv) 2372 void *data, struct drm_file *file_priv)
2372 { 2373 {
2373 struct drm_mode_fb_cmd2 *r = data; 2374 struct drm_mode_fb_cmd2 *r = data;
2374 struct drm_mode_config *config = &dev->mode_config; 2375 struct drm_mode_config *config = &dev->mode_config;
2375 struct drm_framebuffer *fb; 2376 struct drm_framebuffer *fb;
2376 int ret; 2377 int ret;
2377 2378
2378 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2379 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2379 return -EINVAL; 2380 return -EINVAL;
2380 2381
2381 if (r->flags & ~DRM_MODE_FB_INTERLACED) { 2382 if (r->flags & ~DRM_MODE_FB_INTERLACED) {
2382 DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); 2383 DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
2383 return -EINVAL; 2384 return -EINVAL;
2384 } 2385 }
2385 2386
2386 if ((config->min_width > r->width) || (r->width > config->max_width)) { 2387 if ((config->min_width > r->width) || (r->width > config->max_width)) {
2387 DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n", 2388 DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
2388 r->width, config->min_width, config->max_width); 2389 r->width, config->min_width, config->max_width);
2389 return -EINVAL; 2390 return -EINVAL;
2390 } 2391 }
2391 if ((config->min_height > r->height) || (r->height > config->max_height)) { 2392 if ((config->min_height > r->height) || (r->height > config->max_height)) {
2392 DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n", 2393 DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
2393 r->height, config->min_height, config->max_height); 2394 r->height, config->min_height, config->max_height);
2394 return -EINVAL; 2395 return -EINVAL;
2395 } 2396 }
2396 2397
2397 ret = framebuffer_check(r); 2398 ret = framebuffer_check(r);
2398 if (ret) 2399 if (ret)
2399 return ret; 2400 return ret;
2400 2401
2401 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r); 2402 fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
2402 if (IS_ERR(fb)) { 2403 if (IS_ERR(fb)) {
2403 DRM_DEBUG_KMS("could not create framebuffer\n"); 2404 DRM_DEBUG_KMS("could not create framebuffer\n");
2404 return PTR_ERR(fb); 2405 return PTR_ERR(fb);
2405 } 2406 }
2406 2407
2407 mutex_lock(&file_priv->fbs_lock); 2408 mutex_lock(&file_priv->fbs_lock);
2408 r->fb_id = fb->base.id; 2409 r->fb_id = fb->base.id;
2409 list_add(&fb->filp_head, &file_priv->fbs); 2410 list_add(&fb->filp_head, &file_priv->fbs);
2410 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id); 2411 DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2411 mutex_unlock(&file_priv->fbs_lock); 2412 mutex_unlock(&file_priv->fbs_lock);
2412 2413
2413 2414
2414 return ret; 2415 return ret;
2415 } 2416 }
2416 2417
2417 /** 2418 /**
2418 * drm_mode_rmfb - remove an FB from the configuration 2419 * drm_mode_rmfb - remove an FB from the configuration
2419 * @dev: drm device for the ioctl 2420 * @dev: drm device for the ioctl
2420 * @data: data pointer for the ioctl 2421 * @data: data pointer for the ioctl
2421 * @file_priv: drm file for the ioctl call 2422 * @file_priv: drm file for the ioctl call
2422 * 2423 *
2423 * Remove the FB specified by the user. 2424 * Remove the FB specified by the user.
2424 * 2425 *
2425 * Called by the user via ioctl. 2426 * Called by the user via ioctl.
2426 * 2427 *
2427 * RETURNS: 2428 * RETURNS:
2428 * Zero on success, errno on failure. 2429 * Zero on success, errno on failure.
2429 */ 2430 */
2430 int drm_mode_rmfb(struct drm_device *dev, 2431 int drm_mode_rmfb(struct drm_device *dev,
2431 void *data, struct drm_file *file_priv) 2432 void *data, struct drm_file *file_priv)
2432 { 2433 {
2433 struct drm_framebuffer *fb = NULL; 2434 struct drm_framebuffer *fb = NULL;
2434 struct drm_framebuffer *fbl = NULL; 2435 struct drm_framebuffer *fbl = NULL;
2435 uint32_t *id = data; 2436 uint32_t *id = data;
2436 int found = 0; 2437 int found = 0;
2437 2438
2438 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2439 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2439 return -EINVAL; 2440 return -EINVAL;
2440 2441
2441 mutex_lock(&file_priv->fbs_lock); 2442 mutex_lock(&file_priv->fbs_lock);
2442 mutex_lock(&dev->mode_config.fb_lock); 2443 mutex_lock(&dev->mode_config.fb_lock);
2443 fb = __drm_framebuffer_lookup(dev, *id); 2444 fb = __drm_framebuffer_lookup(dev, *id);
2444 if (!fb) 2445 if (!fb)
2445 goto fail_lookup; 2446 goto fail_lookup;
2446 2447
2447 list_for_each_entry(fbl, &file_priv->fbs, filp_head) 2448 list_for_each_entry(fbl, &file_priv->fbs, filp_head)
2448 if (fb == fbl) 2449 if (fb == fbl)
2449 found = 1; 2450 found = 1;
2450 if (!found) 2451 if (!found)
2451 goto fail_lookup; 2452 goto fail_lookup;
2452 2453
2453 /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ 2454 /* Mark fb as reaped, we still have a ref from fpriv->fbs. */
2454 __drm_framebuffer_unregister(dev, fb); 2455 __drm_framebuffer_unregister(dev, fb);
2455 2456
2456 list_del_init(&fb->filp_head); 2457 list_del_init(&fb->filp_head);
2457 mutex_unlock(&dev->mode_config.fb_lock); 2458 mutex_unlock(&dev->mode_config.fb_lock);
2458 mutex_unlock(&file_priv->fbs_lock); 2459 mutex_unlock(&file_priv->fbs_lock);
2459 2460
2460 drm_framebuffer_remove(fb); 2461 drm_framebuffer_remove(fb);
2461 2462
2462 return 0; 2463 return 0;
2463 2464
2464 fail_lookup: 2465 fail_lookup:
2465 mutex_unlock(&dev->mode_config.fb_lock); 2466 mutex_unlock(&dev->mode_config.fb_lock);
2466 mutex_unlock(&file_priv->fbs_lock); 2467 mutex_unlock(&file_priv->fbs_lock);
2467 2468
2468 return -EINVAL; 2469 return -EINVAL;
2469 } 2470 }
2470 2471
2471 /** 2472 /**
2472 * drm_mode_getfb - get FB info 2473 * drm_mode_getfb - get FB info
2473 * @dev: drm device for the ioctl 2474 * @dev: drm device for the ioctl
2474 * @data: data pointer for the ioctl 2475 * @data: data pointer for the ioctl
2475 * @file_priv: drm file for the ioctl call 2476 * @file_priv: drm file for the ioctl call
2476 * 2477 *
2477 * Lookup the FB given its ID and return info about it. 2478 * Lookup the FB given its ID and return info about it.
2478 * 2479 *
2479 * Called by the user via ioctl. 2480 * Called by the user via ioctl.
2480 * 2481 *
2481 * RETURNS: 2482 * RETURNS:
2482 * Zero on success, errno on failure. 2483 * Zero on success, errno on failure.
2483 */ 2484 */
2484 int drm_mode_getfb(struct drm_device *dev, 2485 int drm_mode_getfb(struct drm_device *dev,
2485 void *data, struct drm_file *file_priv) 2486 void *data, struct drm_file *file_priv)
2486 { 2487 {
2487 struct drm_mode_fb_cmd *r = data; 2488 struct drm_mode_fb_cmd *r = data;
2488 struct drm_framebuffer *fb; 2489 struct drm_framebuffer *fb;
2489 int ret; 2490 int ret;
2490 2491
2491 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2492 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2492 return -EINVAL; 2493 return -EINVAL;
2493 2494
2494 fb = drm_framebuffer_lookup(dev, r->fb_id); 2495 fb = drm_framebuffer_lookup(dev, r->fb_id);
2495 if (!fb) 2496 if (!fb)
2496 return -EINVAL; 2497 return -EINVAL;
2497 2498
2498 r->height = fb->height; 2499 r->height = fb->height;
2499 r->width = fb->width; 2500 r->width = fb->width;
2500 r->depth = fb->depth; 2501 r->depth = fb->depth;
2501 r->bpp = fb->bits_per_pixel; 2502 r->bpp = fb->bits_per_pixel;
2502 r->pitch = fb->pitches[0]; 2503 r->pitch = fb->pitches[0];
2503 if (fb->funcs->create_handle) 2504 if (fb->funcs->create_handle)
2504 ret = fb->funcs->create_handle(fb, file_priv, &r->handle); 2505 ret = fb->funcs->create_handle(fb, file_priv, &r->handle);
2505 else 2506 else
2506 ret = -ENODEV; 2507 ret = -ENODEV;
2507 2508
2508 drm_framebuffer_unreference(fb); 2509 drm_framebuffer_unreference(fb);
2509 2510
2510 return ret; 2511 return ret;
2511 } 2512 }
2512 2513
2513 int drm_mode_dirtyfb_ioctl(struct drm_device *dev, 2514 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2514 void *data, struct drm_file *file_priv) 2515 void *data, struct drm_file *file_priv)
2515 { 2516 {
2516 struct drm_clip_rect __user *clips_ptr; 2517 struct drm_clip_rect __user *clips_ptr;
2517 struct drm_clip_rect *clips = NULL; 2518 struct drm_clip_rect *clips = NULL;
2518 struct drm_mode_fb_dirty_cmd *r = data; 2519 struct drm_mode_fb_dirty_cmd *r = data;
2519 struct drm_framebuffer *fb; 2520 struct drm_framebuffer *fb;
2520 unsigned flags; 2521 unsigned flags;
2521 int num_clips; 2522 int num_clips;
2522 int ret; 2523 int ret;
2523 2524
2524 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2525 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2525 return -EINVAL; 2526 return -EINVAL;
2526 2527
2527 fb = drm_framebuffer_lookup(dev, r->fb_id); 2528 fb = drm_framebuffer_lookup(dev, r->fb_id);
2528 if (!fb) 2529 if (!fb)
2529 return -EINVAL; 2530 return -EINVAL;
2530 2531
2531 num_clips = r->num_clips; 2532 num_clips = r->num_clips;
2532 clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr; 2533 clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
2533 2534
2534 if (!num_clips != !clips_ptr) { 2535 if (!num_clips != !clips_ptr) {
2535 ret = -EINVAL; 2536 ret = -EINVAL;
2536 goto out_err1; 2537 goto out_err1;
2537 } 2538 }
2538 2539
2539 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags; 2540 flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
2540 2541
2541 /* If userspace annotates copy, clips must come in pairs */ 2542 /* If userspace annotates copy, clips must come in pairs */
2542 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) { 2543 if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
2543 ret = -EINVAL; 2544 ret = -EINVAL;
2544 goto out_err1; 2545 goto out_err1;
2545 } 2546 }
2546 2547
2547 if (num_clips && clips_ptr) { 2548 if (num_clips && clips_ptr) {
2548 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) { 2549 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
2549 ret = -EINVAL; 2550 ret = -EINVAL;
2550 goto out_err1; 2551 goto out_err1;
2551 } 2552 }
2552 clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); 2553 clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
2553 if (!clips) { 2554 if (!clips) {
2554 ret = -ENOMEM; 2555 ret = -ENOMEM;
2555 goto out_err1; 2556 goto out_err1;
2556 } 2557 }
2557 2558
2558 ret = copy_from_user(clips, clips_ptr, 2559 ret = copy_from_user(clips, clips_ptr,
2559 num_clips * sizeof(*clips)); 2560 num_clips * sizeof(*clips));
2560 if (ret) { 2561 if (ret) {
2561 ret = -EFAULT; 2562 ret = -EFAULT;
2562 goto out_err2; 2563 goto out_err2;
2563 } 2564 }
2564 } 2565 }
2565 2566
2566 if (fb->funcs->dirty) { 2567 if (fb->funcs->dirty) {
2567 drm_modeset_lock_all(dev); 2568 drm_modeset_lock_all(dev);
2568 ret = fb->funcs->dirty(fb, file_priv, flags, r->color, 2569 ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
2569 clips, num_clips); 2570 clips, num_clips);
2570 drm_modeset_unlock_all(dev); 2571 drm_modeset_unlock_all(dev);
2571 } else { 2572 } else {
2572 ret = -ENOSYS; 2573 ret = -ENOSYS;
2573 } 2574 }
2574 2575
2575 out_err2: 2576 out_err2:
2576 kfree(clips); 2577 kfree(clips);
2577 out_err1: 2578 out_err1:
2578 drm_framebuffer_unreference(fb); 2579 drm_framebuffer_unreference(fb);
2579 2580
2580 return ret; 2581 return ret;
2581 } 2582 }
2582 2583
2583 2584
2584 /** 2585 /**
2585 * drm_fb_release - remove and free the FBs on this file 2586 * drm_fb_release - remove and free the FBs on this file
2586 * @priv: drm file for the ioctl 2587 * @priv: drm file for the ioctl
2587 * 2588 *
2588 * Destroy all the FBs associated with @filp. 2589 * Destroy all the FBs associated with @filp.
2589 * 2590 *
2590 * Called by the user via ioctl. 2591 * Called by the user via ioctl.
2591 * 2592 *
2592 * RETURNS: 2593 * RETURNS:
2593 * Zero on success, errno on failure. 2594 * Zero on success, errno on failure.
2594 */ 2595 */
2595 void drm_fb_release(struct drm_file *priv) 2596 void drm_fb_release(struct drm_file *priv)
2596 { 2597 {
2597 struct drm_device *dev = priv->minor->dev; 2598 struct drm_device *dev = priv->minor->dev;
2598 struct drm_framebuffer *fb, *tfb; 2599 struct drm_framebuffer *fb, *tfb;
2599 2600
2600 mutex_lock(&priv->fbs_lock); 2601 mutex_lock(&priv->fbs_lock);
2601 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) { 2602 list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2602 2603
2603 mutex_lock(&dev->mode_config.fb_lock); 2604 mutex_lock(&dev->mode_config.fb_lock);
2604 /* Mark fb as reaped, we still have a ref from fpriv->fbs. */ 2605 /* Mark fb as reaped, we still have a ref from fpriv->fbs. */
2605 __drm_framebuffer_unregister(dev, fb); 2606 __drm_framebuffer_unregister(dev, fb);
2606 mutex_unlock(&dev->mode_config.fb_lock); 2607 mutex_unlock(&dev->mode_config.fb_lock);
2607 2608
2608 list_del_init(&fb->filp_head); 2609 list_del_init(&fb->filp_head);
2609 2610
2610 /* This will also drop the fpriv->fbs reference. */ 2611 /* This will also drop the fpriv->fbs reference. */
2611 drm_framebuffer_remove(fb); 2612 drm_framebuffer_remove(fb);
2612 } 2613 }
2613 mutex_unlock(&priv->fbs_lock); 2614 mutex_unlock(&priv->fbs_lock);
2614 } 2615 }
2615 2616
2616 struct drm_property *drm_property_create(struct drm_device *dev, int flags, 2617 struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2617 const char *name, int num_values) 2618 const char *name, int num_values)
2618 { 2619 {
2619 struct drm_property *property = NULL; 2620 struct drm_property *property = NULL;
2620 int ret; 2621 int ret;
2621 2622
2622 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL); 2623 property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
2623 if (!property) 2624 if (!property)
2624 return NULL; 2625 return NULL;
2625 2626
2626 if (num_values) { 2627 if (num_values) {
2627 property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); 2628 property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
2628 if (!property->values) 2629 if (!property->values)
2629 goto fail; 2630 goto fail;
2630 } 2631 }
2631 2632
2632 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY); 2633 ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
2633 if (ret) 2634 if (ret)
2634 goto fail; 2635 goto fail;
2635 2636
2636 property->flags = flags; 2637 property->flags = flags;
2637 property->num_values = num_values; 2638 property->num_values = num_values;
2638 INIT_LIST_HEAD(&property->enum_blob_list); 2639 INIT_LIST_HEAD(&property->enum_blob_list);
2639 2640
2640 if (name) { 2641 if (name) {
2641 strncpy(property->name, name, DRM_PROP_NAME_LEN); 2642 strncpy(property->name, name, DRM_PROP_NAME_LEN);
2642 property->name[DRM_PROP_NAME_LEN-1] = '\0'; 2643 property->name[DRM_PROP_NAME_LEN-1] = '\0';
2643 } 2644 }
2644 2645
2645 list_add_tail(&property->head, &dev->mode_config.property_list); 2646 list_add_tail(&property->head, &dev->mode_config.property_list);
2646 return property; 2647 return property;
2647 fail: 2648 fail:
2648 kfree(property->values); 2649 kfree(property->values);
2649 kfree(property); 2650 kfree(property);
2650 return NULL; 2651 return NULL;
2651 } 2652 }
2652 EXPORT_SYMBOL(drm_property_create); 2653 EXPORT_SYMBOL(drm_property_create);
2653 2654
2654 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags, 2655 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2655 const char *name, 2656 const char *name,
2656 const struct drm_prop_enum_list *props, 2657 const struct drm_prop_enum_list *props,
2657 int num_values) 2658 int num_values)
2658 { 2659 {
2659 struct drm_property *property; 2660 struct drm_property *property;
2660 int i, ret; 2661 int i, ret;
2661 2662
2662 flags |= DRM_MODE_PROP_ENUM; 2663 flags |= DRM_MODE_PROP_ENUM;
2663 2664
2664 property = drm_property_create(dev, flags, name, num_values); 2665 property = drm_property_create(dev, flags, name, num_values);
2665 if (!property) 2666 if (!property)
2666 return NULL; 2667 return NULL;
2667 2668
2668 for (i = 0; i < num_values; i++) { 2669 for (i = 0; i < num_values; i++) {
2669 ret = drm_property_add_enum(property, i, 2670 ret = drm_property_add_enum(property, i,
2670 props[i].type, 2671 props[i].type,
2671 props[i].name); 2672 props[i].name);
2672 if (ret) { 2673 if (ret) {
2673 drm_property_destroy(dev, property); 2674 drm_property_destroy(dev, property);
2674 return NULL; 2675 return NULL;
2675 } 2676 }
2676 } 2677 }
2677 2678
2678 return property; 2679 return property;
2679 } 2680 }
2680 EXPORT_SYMBOL(drm_property_create_enum); 2681 EXPORT_SYMBOL(drm_property_create_enum);
2681 2682
2682 struct drm_property *drm_property_create_bitmask(struct drm_device *dev, 2683 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
2683 int flags, const char *name, 2684 int flags, const char *name,
2684 const struct drm_prop_enum_list *props, 2685 const struct drm_prop_enum_list *props,
2685 int num_values) 2686 int num_values)
2686 { 2687 {
2687 struct drm_property *property; 2688 struct drm_property *property;
2688 int i, ret; 2689 int i, ret;
2689 2690
2690 flags |= DRM_MODE_PROP_BITMASK; 2691 flags |= DRM_MODE_PROP_BITMASK;
2691 2692
2692 property = drm_property_create(dev, flags, name, num_values); 2693 property = drm_property_create(dev, flags, name, num_values);
2693 if (!property) 2694 if (!property)
2694 return NULL; 2695 return NULL;
2695 2696
2696 for (i = 0; i < num_values; i++) { 2697 for (i = 0; i < num_values; i++) {
2697 ret = drm_property_add_enum(property, i, 2698 ret = drm_property_add_enum(property, i,
2698 props[i].type, 2699 props[i].type,
2699 props[i].name); 2700 props[i].name);
2700 if (ret) { 2701 if (ret) {
2701 drm_property_destroy(dev, property); 2702 drm_property_destroy(dev, property);
2702 return NULL; 2703 return NULL;
2703 } 2704 }
2704 } 2705 }
2705 2706
2706 return property; 2707 return property;
2707 } 2708 }
2708 EXPORT_SYMBOL(drm_property_create_bitmask); 2709 EXPORT_SYMBOL(drm_property_create_bitmask);
2709 2710
2710 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, 2711 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2711 const char *name, 2712 const char *name,
2712 uint64_t min, uint64_t max) 2713 uint64_t min, uint64_t max)
2713 { 2714 {
2714 struct drm_property *property; 2715 struct drm_property *property;
2715 2716
2716 flags |= DRM_MODE_PROP_RANGE; 2717 flags |= DRM_MODE_PROP_RANGE;
2717 2718
2718 property = drm_property_create(dev, flags, name, 2); 2719 property = drm_property_create(dev, flags, name, 2);
2719 if (!property) 2720 if (!property)
2720 return NULL; 2721 return NULL;
2721 2722
2722 property->values[0] = min; 2723 property->values[0] = min;
2723 property->values[1] = max; 2724 property->values[1] = max;
2724 2725
2725 return property; 2726 return property;
2726 } 2727 }
2727 EXPORT_SYMBOL(drm_property_create_range); 2728 EXPORT_SYMBOL(drm_property_create_range);
2728 2729
2729 int drm_property_add_enum(struct drm_property *property, int index, 2730 int drm_property_add_enum(struct drm_property *property, int index,
2730 uint64_t value, const char *name) 2731 uint64_t value, const char *name)
2731 { 2732 {
2732 struct drm_property_enum *prop_enum; 2733 struct drm_property_enum *prop_enum;
2733 2734
2734 if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK))) 2735 if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
2735 return -EINVAL; 2736 return -EINVAL;
2736 2737
2737 /* 2738 /*
2738 * Bitmask enum properties have the additional constraint of values 2739 * Bitmask enum properties have the additional constraint of values
2739 * from 0 to 63 2740 * from 0 to 63
2740 */ 2741 */
2741 if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63)) 2742 if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
2742 return -EINVAL; 2743 return -EINVAL;
2743 2744
2744 if (!list_empty(&property->enum_blob_list)) { 2745 if (!list_empty(&property->enum_blob_list)) {
2745 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2746 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2746 if (prop_enum->value == value) { 2747 if (prop_enum->value == value) {
2747 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2748 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2748 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2749 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2749 return 0; 2750 return 0;
2750 } 2751 }
2751 } 2752 }
2752 } 2753 }
2753 2754
2754 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL); 2755 prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
2755 if (!prop_enum) 2756 if (!prop_enum)
2756 return -ENOMEM; 2757 return -ENOMEM;
2757 2758
2758 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN); 2759 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2759 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0'; 2760 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2760 prop_enum->value = value; 2761 prop_enum->value = value;
2761 2762
2762 property->values[index] = value; 2763 property->values[index] = value;
2763 list_add_tail(&prop_enum->head, &property->enum_blob_list); 2764 list_add_tail(&prop_enum->head, &property->enum_blob_list);
2764 return 0; 2765 return 0;
2765 } 2766 }
2766 EXPORT_SYMBOL(drm_property_add_enum); 2767 EXPORT_SYMBOL(drm_property_add_enum);
2767 2768
2768 void drm_property_destroy(struct drm_device *dev, struct drm_property *property) 2769 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2769 { 2770 {
2770 struct drm_property_enum *prop_enum, *pt; 2771 struct drm_property_enum *prop_enum, *pt;
2771 2772
2772 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) { 2773 list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2773 list_del(&prop_enum->head); 2774 list_del(&prop_enum->head);
2774 kfree(prop_enum); 2775 kfree(prop_enum);
2775 } 2776 }
2776 2777
2777 if (property->num_values) 2778 if (property->num_values)
2778 kfree(property->values); 2779 kfree(property->values);
2779 drm_mode_object_put(dev, &property->base); 2780 drm_mode_object_put(dev, &property->base);
2780 list_del(&property->head); 2781 list_del(&property->head);
2781 kfree(property); 2782 kfree(property);
2782 } 2783 }
2783 EXPORT_SYMBOL(drm_property_destroy); 2784 EXPORT_SYMBOL(drm_property_destroy);
2784 2785
2785 void drm_object_attach_property(struct drm_mode_object *obj, 2786 void drm_object_attach_property(struct drm_mode_object *obj,
2786 struct drm_property *property, 2787 struct drm_property *property,
2787 uint64_t init_val) 2788 uint64_t init_val)
2788 { 2789 {
2789 int count = obj->properties->count; 2790 int count = obj->properties->count;
2790 2791
2791 if (count == DRM_OBJECT_MAX_PROPERTY) { 2792 if (count == DRM_OBJECT_MAX_PROPERTY) {
2792 WARN(1, "Failed to attach object property (type: 0x%x). Please " 2793 WARN(1, "Failed to attach object property (type: 0x%x). Please "
2793 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time " 2794 "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
2794 "you see this message on the same object type.\n", 2795 "you see this message on the same object type.\n",
2795 obj->type); 2796 obj->type);
2796 return; 2797 return;
2797 } 2798 }
2798 2799
2799 obj->properties->ids[count] = property->base.id; 2800 obj->properties->ids[count] = property->base.id;
2800 obj->properties->values[count] = init_val; 2801 obj->properties->values[count] = init_val;
2801 obj->properties->count++; 2802 obj->properties->count++;
2802 } 2803 }
2803 EXPORT_SYMBOL(drm_object_attach_property); 2804 EXPORT_SYMBOL(drm_object_attach_property);
2804 2805
2805 int drm_object_property_set_value(struct drm_mode_object *obj, 2806 int drm_object_property_set_value(struct drm_mode_object *obj,
2806 struct drm_property *property, uint64_t val) 2807 struct drm_property *property, uint64_t val)
2807 { 2808 {
2808 int i; 2809 int i;
2809 2810
2810 for (i = 0; i < obj->properties->count; i++) { 2811 for (i = 0; i < obj->properties->count; i++) {
2811 if (obj->properties->ids[i] == property->base.id) { 2812 if (obj->properties->ids[i] == property->base.id) {
2812 obj->properties->values[i] = val; 2813 obj->properties->values[i] = val;
2813 return 0; 2814 return 0;
2814 } 2815 }
2815 } 2816 }
2816 2817
2817 return -EINVAL; 2818 return -EINVAL;
2818 } 2819 }
2819 EXPORT_SYMBOL(drm_object_property_set_value); 2820 EXPORT_SYMBOL(drm_object_property_set_value);
2820 2821
2821 int drm_object_property_get_value(struct drm_mode_object *obj, 2822 int drm_object_property_get_value(struct drm_mode_object *obj,
2822 struct drm_property *property, uint64_t *val) 2823 struct drm_property *property, uint64_t *val)
2823 { 2824 {
2824 int i; 2825 int i;
2825 2826
2826 for (i = 0; i < obj->properties->count; i++) { 2827 for (i = 0; i < obj->properties->count; i++) {
2827 if (obj->properties->ids[i] == property->base.id) { 2828 if (obj->properties->ids[i] == property->base.id) {
2828 *val = obj->properties->values[i]; 2829 *val = obj->properties->values[i];
2829 return 0; 2830 return 0;
2830 } 2831 }
2831 } 2832 }
2832 2833
2833 return -EINVAL; 2834 return -EINVAL;
2834 } 2835 }
2835 EXPORT_SYMBOL(drm_object_property_get_value); 2836 EXPORT_SYMBOL(drm_object_property_get_value);
2836 2837
2837 int drm_mode_getproperty_ioctl(struct drm_device *dev, 2838 int drm_mode_getproperty_ioctl(struct drm_device *dev,
2838 void *data, struct drm_file *file_priv) 2839 void *data, struct drm_file *file_priv)
2839 { 2840 {
2840 struct drm_mode_object *obj; 2841 struct drm_mode_object *obj;
2841 struct drm_mode_get_property *out_resp = data; 2842 struct drm_mode_get_property *out_resp = data;
2842 struct drm_property *property; 2843 struct drm_property *property;
2843 int enum_count = 0; 2844 int enum_count = 0;
2844 int blob_count = 0; 2845 int blob_count = 0;
2845 int value_count = 0; 2846 int value_count = 0;
2846 int ret = 0, i; 2847 int ret = 0, i;
2847 int copied; 2848 int copied;
2848 struct drm_property_enum *prop_enum; 2849 struct drm_property_enum *prop_enum;
2849 struct drm_mode_property_enum __user *enum_ptr; 2850 struct drm_mode_property_enum __user *enum_ptr;
2850 struct drm_property_blob *prop_blob; 2851 struct drm_property_blob *prop_blob;
2851 uint32_t __user *blob_id_ptr; 2852 uint32_t __user *blob_id_ptr;
2852 uint64_t __user *values_ptr; 2853 uint64_t __user *values_ptr;
2853 uint32_t __user *blob_length_ptr; 2854 uint32_t __user *blob_length_ptr;
2854 2855
2855 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2856 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2856 return -EINVAL; 2857 return -EINVAL;
2857 2858
2858 drm_modeset_lock_all(dev); 2859 drm_modeset_lock_all(dev);
2859 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY); 2860 obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2860 if (!obj) { 2861 if (!obj) {
2861 ret = -EINVAL; 2862 ret = -EINVAL;
2862 goto done; 2863 goto done;
2863 } 2864 }
2864 property = obj_to_property(obj); 2865 property = obj_to_property(obj);
2865 2866
2866 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 2867 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2867 list_for_each_entry(prop_enum, &property->enum_blob_list, head) 2868 list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2868 enum_count++; 2869 enum_count++;
2869 } else if (property->flags & DRM_MODE_PROP_BLOB) { 2870 } else if (property->flags & DRM_MODE_PROP_BLOB) {
2870 list_for_each_entry(prop_blob, &property->enum_blob_list, head) 2871 list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2871 blob_count++; 2872 blob_count++;
2872 } 2873 }
2873 2874
2874 value_count = property->num_values; 2875 value_count = property->num_values;
2875 2876
2876 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN); 2877 strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2877 out_resp->name[DRM_PROP_NAME_LEN-1] = 0; 2878 out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2878 out_resp->flags = property->flags; 2879 out_resp->flags = property->flags;
2879 2880
2880 if ((out_resp->count_values >= value_count) && value_count) { 2881 if ((out_resp->count_values >= value_count) && value_count) {
2881 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr; 2882 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
2882 for (i = 0; i < value_count; i++) { 2883 for (i = 0; i < value_count; i++) {
2883 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) { 2884 if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
2884 ret = -EFAULT; 2885 ret = -EFAULT;
2885 goto done; 2886 goto done;
2886 } 2887 }
2887 } 2888 }
2888 } 2889 }
2889 out_resp->count_values = value_count; 2890 out_resp->count_values = value_count;
2890 2891
2891 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) { 2892 if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
2892 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) { 2893 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2893 copied = 0; 2894 copied = 0;
2894 enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr; 2895 enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
2895 list_for_each_entry(prop_enum, &property->enum_blob_list, head) { 2896 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2896 2897
2897 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) { 2898 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
2898 ret = -EFAULT; 2899 ret = -EFAULT;
2899 goto done; 2900 goto done;
2900 } 2901 }
2901 2902
2902 if (copy_to_user(&enum_ptr[copied].name, 2903 if (copy_to_user(&enum_ptr[copied].name,
2903 &prop_enum->name, DRM_PROP_NAME_LEN)) { 2904 &prop_enum->name, DRM_PROP_NAME_LEN)) {
2904 ret = -EFAULT; 2905 ret = -EFAULT;
2905 goto done; 2906 goto done;
2906 } 2907 }
2907 copied++; 2908 copied++;
2908 } 2909 }
2909 } 2910 }
2910 out_resp->count_enum_blobs = enum_count; 2911 out_resp->count_enum_blobs = enum_count;
2911 } 2912 }
2912 2913
2913 if (property->flags & DRM_MODE_PROP_BLOB) { 2914 if (property->flags & DRM_MODE_PROP_BLOB) {
2914 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) { 2915 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2915 copied = 0; 2916 copied = 0;
2916 blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr; 2917 blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
2917 blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr; 2918 blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
2918 2919
2919 list_for_each_entry(prop_blob, &property->enum_blob_list, head) { 2920 list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2920 if (put_user(prop_blob->base.id, blob_id_ptr + copied)) { 2921 if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
2921 ret = -EFAULT; 2922 ret = -EFAULT;
2922 goto done; 2923 goto done;
2923 } 2924 }
2924 2925
2925 if (put_user(prop_blob->length, blob_length_ptr + copied)) { 2926 if (put_user(prop_blob->length, blob_length_ptr + copied)) {
2926 ret = -EFAULT; 2927 ret = -EFAULT;
2927 goto done; 2928 goto done;
2928 } 2929 }
2929 2930
2930 copied++; 2931 copied++;
2931 } 2932 }
2932 } 2933 }
2933 out_resp->count_enum_blobs = blob_count; 2934 out_resp->count_enum_blobs = blob_count;
2934 } 2935 }
2935 done: 2936 done:
2936 drm_modeset_unlock_all(dev); 2937 drm_modeset_unlock_all(dev);
2937 return ret; 2938 return ret;
2938 } 2939 }
2939 2940
2940 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length, 2941 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
2941 void *data) 2942 void *data)
2942 { 2943 {
2943 struct drm_property_blob *blob; 2944 struct drm_property_blob *blob;
2944 int ret; 2945 int ret;
2945 2946
2946 if (!length || !data) 2947 if (!length || !data)
2947 return NULL; 2948 return NULL;
2948 2949
2949 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL); 2950 blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
2950 if (!blob) 2951 if (!blob)
2951 return NULL; 2952 return NULL;
2952 2953
2953 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB); 2954 ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
2954 if (ret) { 2955 if (ret) {
2955 kfree(blob); 2956 kfree(blob);
2956 return NULL; 2957 return NULL;
2957 } 2958 }
2958 2959
2959 blob->length = length; 2960 blob->length = length;
2960 2961
2961 memcpy(blob->data, data, length); 2962 memcpy(blob->data, data, length);
2962 2963
2963 list_add_tail(&blob->head, &dev->mode_config.property_blob_list); 2964 list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
2964 return blob; 2965 return blob;
2965 } 2966 }
2966 2967
2967 static void drm_property_destroy_blob(struct drm_device *dev, 2968 static void drm_property_destroy_blob(struct drm_device *dev,
2968 struct drm_property_blob *blob) 2969 struct drm_property_blob *blob)
2969 { 2970 {
2970 drm_mode_object_put(dev, &blob->base); 2971 drm_mode_object_put(dev, &blob->base);
2971 list_del(&blob->head); 2972 list_del(&blob->head);
2972 kfree(blob); 2973 kfree(blob);
2973 } 2974 }
2974 2975
2975 int drm_mode_getblob_ioctl(struct drm_device *dev, 2976 int drm_mode_getblob_ioctl(struct drm_device *dev,
2976 void *data, struct drm_file *file_priv) 2977 void *data, struct drm_file *file_priv)
2977 { 2978 {
2978 struct drm_mode_object *obj; 2979 struct drm_mode_object *obj;
2979 struct drm_mode_get_blob *out_resp = data; 2980 struct drm_mode_get_blob *out_resp = data;
2980 struct drm_property_blob *blob; 2981 struct drm_property_blob *blob;
2981 int ret = 0; 2982 int ret = 0;
2982 void __user *blob_ptr; 2983 void __user *blob_ptr;
2983 2984
2984 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 2985 if (!drm_core_check_feature(dev, DRIVER_MODESET))
2985 return -EINVAL; 2986 return -EINVAL;
2986 2987
2987 drm_modeset_lock_all(dev); 2988 drm_modeset_lock_all(dev);
2988 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB); 2989 obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
2989 if (!obj) { 2990 if (!obj) {
2990 ret = -EINVAL; 2991 ret = -EINVAL;
2991 goto done; 2992 goto done;
2992 } 2993 }
2993 blob = obj_to_blob(obj); 2994 blob = obj_to_blob(obj);
2994 2995
2995 if (out_resp->length == blob->length) { 2996 if (out_resp->length == blob->length) {
2996 blob_ptr = (void __user *)(unsigned long)out_resp->data; 2997 blob_ptr = (void __user *)(unsigned long)out_resp->data;
2997 if (copy_to_user(blob_ptr, blob->data, blob->length)){ 2998 if (copy_to_user(blob_ptr, blob->data, blob->length)){
2998 ret = -EFAULT; 2999 ret = -EFAULT;
2999 goto done; 3000 goto done;
3000 } 3001 }
3001 } 3002 }
3002 out_resp->length = blob->length; 3003 out_resp->length = blob->length;
3003 3004
3004 done: 3005 done:
3005 drm_modeset_unlock_all(dev); 3006 drm_modeset_unlock_all(dev);
3006 return ret; 3007 return ret;
3007 } 3008 }
3008 3009
3009 int drm_mode_connector_update_edid_property(struct drm_connector *connector, 3010 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
3010 struct edid *edid) 3011 struct edid *edid)
3011 { 3012 {
3012 struct drm_device *dev = connector->dev; 3013 struct drm_device *dev = connector->dev;
3013 int ret, size; 3014 int ret, size;
3014 3015
3015 if (connector->edid_blob_ptr) 3016 if (connector->edid_blob_ptr)
3016 drm_property_destroy_blob(dev, connector->edid_blob_ptr); 3017 drm_property_destroy_blob(dev, connector->edid_blob_ptr);
3017 3018
3018 /* Delete edid, when there is none. */ 3019 /* Delete edid, when there is none. */
3019 if (!edid) { 3020 if (!edid) {
3020 connector->edid_blob_ptr = NULL; 3021 connector->edid_blob_ptr = NULL;
3021 ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0); 3022 ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
3022 return ret; 3023 return ret;
3023 } 3024 }
3024 3025
3025 size = EDID_LENGTH * (1 + edid->extensions); 3026 size = EDID_LENGTH * (1 + edid->extensions);
3026 connector->edid_blob_ptr = drm_property_create_blob(connector->dev, 3027 connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
3027 size, edid); 3028 size, edid);
3028 if (!connector->edid_blob_ptr) 3029 if (!connector->edid_blob_ptr)
3029 return -EINVAL; 3030 return -EINVAL;
3030 3031
3031 ret = drm_object_property_set_value(&connector->base, 3032 ret = drm_object_property_set_value(&connector->base,
3032 dev->mode_config.edid_property, 3033 dev->mode_config.edid_property,
3033 connector->edid_blob_ptr->base.id); 3034 connector->edid_blob_ptr->base.id);
3034 3035
3035 return ret; 3036 return ret;
3036 } 3037 }
3037 EXPORT_SYMBOL(drm_mode_connector_update_edid_property); 3038 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
3038 3039
3039 static bool drm_property_change_is_valid(struct drm_property *property, 3040 static bool drm_property_change_is_valid(struct drm_property *property,
3040 uint64_t value) 3041 uint64_t value)
3041 { 3042 {
3042 if (property->flags & DRM_MODE_PROP_IMMUTABLE) 3043 if (property->flags & DRM_MODE_PROP_IMMUTABLE)
3043 return false; 3044 return false;
3044 if (property->flags & DRM_MODE_PROP_RANGE) { 3045 if (property->flags & DRM_MODE_PROP_RANGE) {
3045 if (value < property->values[0] || value > property->values[1]) 3046 if (value < property->values[0] || value > property->values[1])
3046 return false; 3047 return false;
3047 return true; 3048 return true;
3048 } else if (property->flags & DRM_MODE_PROP_BITMASK) { 3049 } else if (property->flags & DRM_MODE_PROP_BITMASK) {
3049 int i; 3050 int i;
3050 uint64_t valid_mask = 0; 3051 uint64_t valid_mask = 0;
3051 for (i = 0; i < property->num_values; i++) 3052 for (i = 0; i < property->num_values; i++)
3052 valid_mask |= (1ULL << property->values[i]); 3053 valid_mask |= (1ULL << property->values[i]);
3053 return !(value & ~valid_mask); 3054 return !(value & ~valid_mask);
3054 } else if (property->flags & DRM_MODE_PROP_BLOB) { 3055 } else if (property->flags & DRM_MODE_PROP_BLOB) {
3055 /* Only the driver knows */ 3056 /* Only the driver knows */
3056 return true; 3057 return true;
3057 } else { 3058 } else {
3058 int i; 3059 int i;
3059 for (i = 0; i < property->num_values; i++) 3060 for (i = 0; i < property->num_values; i++)
3060 if (property->values[i] == value) 3061 if (property->values[i] == value)
3061 return true; 3062 return true;
3062 return false; 3063 return false;
3063 } 3064 }
3064 } 3065 }
3065 3066
3066 int drm_mode_connector_property_set_ioctl(struct drm_device *dev, 3067 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
3067 void *data, struct drm_file *file_priv) 3068 void *data, struct drm_file *file_priv)
3068 { 3069 {
3069 struct drm_mode_connector_set_property *conn_set_prop = data; 3070 struct drm_mode_connector_set_property *conn_set_prop = data;
3070 struct drm_mode_obj_set_property obj_set_prop = { 3071 struct drm_mode_obj_set_property obj_set_prop = {
3071 .value = conn_set_prop->value, 3072 .value = conn_set_prop->value,
3072 .prop_id = conn_set_prop->prop_id, 3073 .prop_id = conn_set_prop->prop_id,
3073 .obj_id = conn_set_prop->connector_id, 3074 .obj_id = conn_set_prop->connector_id,
3074 .obj_type = DRM_MODE_OBJECT_CONNECTOR 3075 .obj_type = DRM_MODE_OBJECT_CONNECTOR
3075 }; 3076 };
3076 3077
3077 /* It does all the locking and checking we need */ 3078 /* It does all the locking and checking we need */
3078 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv); 3079 return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
3079 } 3080 }
3080 3081
3081 static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, 3082 static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
3082 struct drm_property *property, 3083 struct drm_property *property,
3083 uint64_t value) 3084 uint64_t value)
3084 { 3085 {
3085 int ret = -EINVAL; 3086 int ret = -EINVAL;
3086 struct drm_connector *connector = obj_to_connector(obj); 3087 struct drm_connector *connector = obj_to_connector(obj);
3087 3088
3088 /* Do DPMS ourselves */ 3089 /* Do DPMS ourselves */
3089 if (property == connector->dev->mode_config.dpms_property) { 3090 if (property == connector->dev->mode_config.dpms_property) {
3090 if (connector->funcs->dpms) 3091 if (connector->funcs->dpms)
3091 (*connector->funcs->dpms)(connector, (int)value); 3092 (*connector->funcs->dpms)(connector, (int)value);
3092 ret = 0; 3093 ret = 0;
3093 } else if (connector->funcs->set_property) 3094 } else if (connector->funcs->set_property)
3094 ret = connector->funcs->set_property(connector, property, value); 3095 ret = connector->funcs->set_property(connector, property, value);
3095 3096
3096 /* store the property value if successful */ 3097 /* store the property value if successful */
3097 if (!ret) 3098 if (!ret)
3098 drm_object_property_set_value(&connector->base, property, value); 3099 drm_object_property_set_value(&connector->base, property, value);
3099 return ret; 3100 return ret;
3100 } 3101 }
3101 3102
3102 static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj, 3103 static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
3103 struct drm_property *property, 3104 struct drm_property *property,
3104 uint64_t value) 3105 uint64_t value)
3105 { 3106 {
3106 int ret = -EINVAL; 3107 int ret = -EINVAL;
3107 struct drm_crtc *crtc = obj_to_crtc(obj); 3108 struct drm_crtc *crtc = obj_to_crtc(obj);
3108 3109
3109 if (crtc->funcs->set_property) 3110 if (crtc->funcs->set_property)
3110 ret = crtc->funcs->set_property(crtc, property, value); 3111 ret = crtc->funcs->set_property(crtc, property, value);
3111 if (!ret) 3112 if (!ret)
3112 drm_object_property_set_value(obj, property, value); 3113 drm_object_property_set_value(obj, property, value);
3113 3114
3114 return ret; 3115 return ret;
3115 } 3116 }
3116 3117
3117 static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj, 3118 static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
3118 struct drm_property *property, 3119 struct drm_property *property,
3119 uint64_t value) 3120 uint64_t value)
3120 { 3121 {
3121 int ret = -EINVAL; 3122 int ret = -EINVAL;
3122 struct drm_plane *plane = obj_to_plane(obj); 3123 struct drm_plane *plane = obj_to_plane(obj);
3123 3124
3124 if (plane->funcs->set_property) 3125 if (plane->funcs->set_property)
3125 ret = plane->funcs->set_property(plane, property, value); 3126 ret = plane->funcs->set_property(plane, property, value);
3126 if (!ret) 3127 if (!ret)
3127 drm_object_property_set_value(obj, property, value); 3128 drm_object_property_set_value(obj, property, value);
3128 3129
3129 return ret; 3130 return ret;
3130 } 3131 }
3131 3132
3132 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, 3133 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
3133 struct drm_file *file_priv) 3134 struct drm_file *file_priv)
3134 { 3135 {
3135 struct drm_mode_obj_get_properties *arg = data; 3136 struct drm_mode_obj_get_properties *arg = data;
3136 struct drm_mode_object *obj; 3137 struct drm_mode_object *obj;
3137 int ret = 0; 3138 int ret = 0;
3138 int i; 3139 int i;
3139 int copied = 0; 3140 int copied = 0;
3140 int props_count = 0; 3141 int props_count = 0;
3141 uint32_t __user *props_ptr; 3142 uint32_t __user *props_ptr;
3142 uint64_t __user *prop_values_ptr; 3143 uint64_t __user *prop_values_ptr;
3143 3144
3144 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3145 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3145 return -EINVAL; 3146 return -EINVAL;
3146 3147
3147 drm_modeset_lock_all(dev); 3148 drm_modeset_lock_all(dev);
3148 3149
3149 obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 3150 obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3150 if (!obj) { 3151 if (!obj) {
3151 ret = -EINVAL; 3152 ret = -EINVAL;
3152 goto out; 3153 goto out;
3153 } 3154 }
3154 if (!obj->properties) { 3155 if (!obj->properties) {
3155 ret = -EINVAL; 3156 ret = -EINVAL;
3156 goto out; 3157 goto out;
3157 } 3158 }
3158 3159
3159 props_count = obj->properties->count; 3160 props_count = obj->properties->count;
3160 3161
3161 /* This ioctl is called twice, once to determine how much space is 3162 /* This ioctl is called twice, once to determine how much space is
3162 * needed, and the 2nd time to fill it. */ 3163 * needed, and the 2nd time to fill it. */
3163 if ((arg->count_props >= props_count) && props_count) { 3164 if ((arg->count_props >= props_count) && props_count) {
3164 copied = 0; 3165 copied = 0;
3165 props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); 3166 props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
3166 prop_values_ptr = (uint64_t __user *)(unsigned long) 3167 prop_values_ptr = (uint64_t __user *)(unsigned long)
3167 (arg->prop_values_ptr); 3168 (arg->prop_values_ptr);
3168 for (i = 0; i < props_count; i++) { 3169 for (i = 0; i < props_count; i++) {
3169 if (put_user(obj->properties->ids[i], 3170 if (put_user(obj->properties->ids[i],
3170 props_ptr + copied)) { 3171 props_ptr + copied)) {
3171 ret = -EFAULT; 3172 ret = -EFAULT;
3172 goto out; 3173 goto out;
3173 } 3174 }
3174 if (put_user(obj->properties->values[i], 3175 if (put_user(obj->properties->values[i],
3175 prop_values_ptr + copied)) { 3176 prop_values_ptr + copied)) {
3176 ret = -EFAULT; 3177 ret = -EFAULT;
3177 goto out; 3178 goto out;
3178 } 3179 }
3179 copied++; 3180 copied++;
3180 } 3181 }
3181 } 3182 }
3182 arg->count_props = props_count; 3183 arg->count_props = props_count;
3183 out: 3184 out:
3184 drm_modeset_unlock_all(dev); 3185 drm_modeset_unlock_all(dev);
3185 return ret; 3186 return ret;
3186 } 3187 }
3187 3188
3188 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, 3189 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
3189 struct drm_file *file_priv) 3190 struct drm_file *file_priv)
3190 { 3191 {
3191 struct drm_mode_obj_set_property *arg = data; 3192 struct drm_mode_obj_set_property *arg = data;
3192 struct drm_mode_object *arg_obj; 3193 struct drm_mode_object *arg_obj;
3193 struct drm_mode_object *prop_obj; 3194 struct drm_mode_object *prop_obj;
3194 struct drm_property *property; 3195 struct drm_property *property;
3195 int ret = -EINVAL; 3196 int ret = -EINVAL;
3196 int i; 3197 int i;
3197 3198
3198 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3199 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3199 return -EINVAL; 3200 return -EINVAL;
3200 3201
3201 drm_modeset_lock_all(dev); 3202 drm_modeset_lock_all(dev);
3202 3203
3203 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); 3204 arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3204 if (!arg_obj) 3205 if (!arg_obj)
3205 goto out; 3206 goto out;
3206 if (!arg_obj->properties) 3207 if (!arg_obj->properties)
3207 goto out; 3208 goto out;
3208 3209
3209 for (i = 0; i < arg_obj->properties->count; i++) 3210 for (i = 0; i < arg_obj->properties->count; i++)
3210 if (arg_obj->properties->ids[i] == arg->prop_id) 3211 if (arg_obj->properties->ids[i] == arg->prop_id)
3211 break; 3212 break;
3212 3213
3213 if (i == arg_obj->properties->count) 3214 if (i == arg_obj->properties->count)
3214 goto out; 3215 goto out;
3215 3216
3216 prop_obj = drm_mode_object_find(dev, arg->prop_id, 3217 prop_obj = drm_mode_object_find(dev, arg->prop_id,
3217 DRM_MODE_OBJECT_PROPERTY); 3218 DRM_MODE_OBJECT_PROPERTY);
3218 if (!prop_obj) 3219 if (!prop_obj)
3219 goto out; 3220 goto out;
3220 property = obj_to_property(prop_obj); 3221 property = obj_to_property(prop_obj);
3221 3222
3222 if (!drm_property_change_is_valid(property, arg->value)) 3223 if (!drm_property_change_is_valid(property, arg->value))
3223 goto out; 3224 goto out;
3224 3225
3225 switch (arg_obj->type) { 3226 switch (arg_obj->type) {
3226 case DRM_MODE_OBJECT_CONNECTOR: 3227 case DRM_MODE_OBJECT_CONNECTOR:
3227 ret = drm_mode_connector_set_obj_prop(arg_obj, property, 3228 ret = drm_mode_connector_set_obj_prop(arg_obj, property,
3228 arg->value); 3229 arg->value);
3229 break; 3230 break;
3230 case DRM_MODE_OBJECT_CRTC: 3231 case DRM_MODE_OBJECT_CRTC:
3231 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value); 3232 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
3232 break; 3233 break;
3233 case DRM_MODE_OBJECT_PLANE: 3234 case DRM_MODE_OBJECT_PLANE:
3234 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value); 3235 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
3235 break; 3236 break;
3236 } 3237 }
3237 3238
3238 out: 3239 out:
3239 drm_modeset_unlock_all(dev); 3240 drm_modeset_unlock_all(dev);
3240 return ret; 3241 return ret;
3241 } 3242 }
3242 3243
3243 int drm_mode_connector_attach_encoder(struct drm_connector *connector, 3244 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
3244 struct drm_encoder *encoder) 3245 struct drm_encoder *encoder)
3245 { 3246 {
3246 int i; 3247 int i;
3247 3248
3248 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3249 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3249 if (connector->encoder_ids[i] == 0) { 3250 if (connector->encoder_ids[i] == 0) {
3250 connector->encoder_ids[i] = encoder->base.id; 3251 connector->encoder_ids[i] = encoder->base.id;
3251 return 0; 3252 return 0;
3252 } 3253 }
3253 } 3254 }
3254 return -ENOMEM; 3255 return -ENOMEM;
3255 } 3256 }
3256 EXPORT_SYMBOL(drm_mode_connector_attach_encoder); 3257 EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
3257 3258
3258 void drm_mode_connector_detach_encoder(struct drm_connector *connector, 3259 void drm_mode_connector_detach_encoder(struct drm_connector *connector,
3259 struct drm_encoder *encoder) 3260 struct drm_encoder *encoder)
3260 { 3261 {
3261 int i; 3262 int i;
3262 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 3263 for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3263 if (connector->encoder_ids[i] == encoder->base.id) { 3264 if (connector->encoder_ids[i] == encoder->base.id) {
3264 connector->encoder_ids[i] = 0; 3265 connector->encoder_ids[i] = 0;
3265 if (connector->encoder == encoder) 3266 if (connector->encoder == encoder)
3266 connector->encoder = NULL; 3267 connector->encoder = NULL;
3267 break; 3268 break;
3268 } 3269 }
3269 } 3270 }
3270 } 3271 }
3271 EXPORT_SYMBOL(drm_mode_connector_detach_encoder); 3272 EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
3272 3273
3273 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, 3274 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
3274 int gamma_size) 3275 int gamma_size)
3275 { 3276 {
3276 crtc->gamma_size = gamma_size; 3277 crtc->gamma_size = gamma_size;
3277 3278
3278 crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL); 3279 crtc->gamma_store = kzalloc(gamma_size * sizeof(uint16_t) * 3, GFP_KERNEL);
3279 if (!crtc->gamma_store) { 3280 if (!crtc->gamma_store) {
3280 crtc->gamma_size = 0; 3281 crtc->gamma_size = 0;
3281 return -ENOMEM; 3282 return -ENOMEM;
3282 } 3283 }
3283 3284
3284 return 0; 3285 return 0;
3285 } 3286 }
3286 EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size); 3287 EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
3287 3288
3288 int drm_mode_gamma_set_ioctl(struct drm_device *dev, 3289 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
3289 void *data, struct drm_file *file_priv) 3290 void *data, struct drm_file *file_priv)
3290 { 3291 {
3291 struct drm_mode_crtc_lut *crtc_lut = data; 3292 struct drm_mode_crtc_lut *crtc_lut = data;
3292 struct drm_mode_object *obj; 3293 struct drm_mode_object *obj;
3293 struct drm_crtc *crtc; 3294 struct drm_crtc *crtc;
3294 void *r_base, *g_base, *b_base; 3295 void *r_base, *g_base, *b_base;
3295 int size; 3296 int size;
3296 int ret = 0; 3297 int ret = 0;
3297 3298
3298 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3299 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3299 return -EINVAL; 3300 return -EINVAL;
3300 3301
3301 drm_modeset_lock_all(dev); 3302 drm_modeset_lock_all(dev);
3302 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3303 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3303 if (!obj) { 3304 if (!obj) {
3304 ret = -EINVAL; 3305 ret = -EINVAL;
3305 goto out; 3306 goto out;
3306 } 3307 }
3307 crtc = obj_to_crtc(obj); 3308 crtc = obj_to_crtc(obj);
3308 3309
3309 if (crtc->funcs->gamma_set == NULL) { 3310 if (crtc->funcs->gamma_set == NULL) {
3310 ret = -ENOSYS; 3311 ret = -ENOSYS;
3311 goto out; 3312 goto out;
3312 } 3313 }
3313 3314
3314 /* memcpy into gamma store */ 3315 /* memcpy into gamma store */
3315 if (crtc_lut->gamma_size != crtc->gamma_size) { 3316 if (crtc_lut->gamma_size != crtc->gamma_size) {
3316 ret = -EINVAL; 3317 ret = -EINVAL;
3317 goto out; 3318 goto out;
3318 } 3319 }
3319 3320
3320 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3321 size = crtc_lut->gamma_size * (sizeof(uint16_t));
3321 r_base = crtc->gamma_store; 3322 r_base = crtc->gamma_store;
3322 if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) { 3323 if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
3323 ret = -EFAULT; 3324 ret = -EFAULT;
3324 goto out; 3325 goto out;
3325 } 3326 }
3326 3327
3327 g_base = r_base + size; 3328 g_base = r_base + size;
3328 if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) { 3329 if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
3329 ret = -EFAULT; 3330 ret = -EFAULT;
3330 goto out; 3331 goto out;
3331 } 3332 }
3332 3333
3333 b_base = g_base + size; 3334 b_base = g_base + size;
3334 if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) { 3335 if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
3335 ret = -EFAULT; 3336 ret = -EFAULT;
3336 goto out; 3337 goto out;
3337 } 3338 }
3338 3339
3339 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); 3340 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
3340 3341
3341 out: 3342 out:
3342 drm_modeset_unlock_all(dev); 3343 drm_modeset_unlock_all(dev);
3343 return ret; 3344 return ret;
3344 3345
3345 } 3346 }
3346 3347
3347 int drm_mode_gamma_get_ioctl(struct drm_device *dev, 3348 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
3348 void *data, struct drm_file *file_priv) 3349 void *data, struct drm_file *file_priv)
3349 { 3350 {
3350 struct drm_mode_crtc_lut *crtc_lut = data; 3351 struct drm_mode_crtc_lut *crtc_lut = data;
3351 struct drm_mode_object *obj; 3352 struct drm_mode_object *obj;
3352 struct drm_crtc *crtc; 3353 struct drm_crtc *crtc;
3353 void *r_base, *g_base, *b_base; 3354 void *r_base, *g_base, *b_base;
3354 int size; 3355 int size;
3355 int ret = 0; 3356 int ret = 0;
3356 3357
3357 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 3358 if (!drm_core_check_feature(dev, DRIVER_MODESET))
3358 return -EINVAL; 3359 return -EINVAL;
3359 3360
3360 drm_modeset_lock_all(dev); 3361 drm_modeset_lock_all(dev);
3361 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC); 3362 obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3362 if (!obj) { 3363 if (!obj) {
3363 ret = -EINVAL; 3364 ret = -EINVAL;
3364 goto out; 3365 goto out;
3365 } 3366 }
3366 crtc = obj_to_crtc(obj); 3367 crtc = obj_to_crtc(obj);
3367 3368
3368 /* memcpy into gamma store */ 3369 /* memcpy into gamma store */
3369 if (crtc_lut->gamma_size != crtc->gamma_size) { 3370 if (crtc_lut->gamma_size != crtc->gamma_size) {
3370 ret = -EINVAL; 3371 ret = -EINVAL;
3371 goto out; 3372 goto out;
3372 } 3373 }
3373 3374
3374 size = crtc_lut->gamma_size * (sizeof(uint16_t)); 3375 size = crtc_lut->gamma_size * (sizeof(uint16_t));
3375 r_base = crtc->gamma_store; 3376 r_base = crtc->gamma_store;
3376 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) { 3377 if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
3377 ret = -EFAULT; 3378 ret = -EFAULT;
3378 goto out; 3379 goto out;
3379 } 3380 }
3380 3381
3381 g_base = r_base + size; 3382 g_base = r_base + size;
3382 if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) { 3383 if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
3383 ret = -EFAULT; 3384 ret = -EFAULT;
3384 goto out; 3385 goto out;
3385 } 3386 }
3386 3387
3387 b_base = g_base + size; 3388 b_base = g_base + size;
3388 if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) { 3389 if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
3389 ret = -EFAULT; 3390 ret = -EFAULT;
3390 goto out; 3391 goto out;
3391 } 3392 }
3392 out: 3393 out:
3393 drm_modeset_unlock_all(dev); 3394 drm_modeset_unlock_all(dev);
3394 return ret; 3395 return ret;
3395 } 3396 }
3396 3397
3397 int drm_mode_page_flip_ioctl(struct drm_device *dev, 3398 int drm_mode_page_flip_ioctl(struct drm_device *dev,
3398 void *data, struct drm_file *file_priv) 3399 void *data, struct drm_file *file_priv)
3399 { 3400 {
3400 struct drm_mode_crtc_page_flip *page_flip = data; 3401 struct drm_mode_crtc_page_flip *page_flip = data;
3401 struct drm_mode_object *obj; 3402 struct drm_mode_object *obj;
3402 struct drm_crtc *crtc; 3403 struct drm_crtc *crtc;
3403 struct drm_framebuffer *fb = NULL, *old_fb = NULL; 3404 struct drm_framebuffer *fb = NULL, *old_fb = NULL;
3404 struct drm_pending_vblank_event *e = NULL; 3405 struct drm_pending_vblank_event *e = NULL;
3405 unsigned long flags; 3406 unsigned long flags;
3406 int hdisplay, vdisplay; 3407 int hdisplay, vdisplay;
3407 int ret = -EINVAL; 3408 int ret = -EINVAL;
3408 3409
3409 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS || 3410 if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
3410 page_flip->reserved != 0) 3411 page_flip->reserved != 0)
3411 return -EINVAL; 3412 return -EINVAL;
3412 3413
3413 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC); 3414 obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
3414 if (!obj) 3415 if (!obj)
3415 return -EINVAL; 3416 return -EINVAL;
3416 crtc = obj_to_crtc(obj); 3417 crtc = obj_to_crtc(obj);
3417 3418
3418 mutex_lock(&crtc->mutex); 3419 mutex_lock(&crtc->mutex);
3419 if (crtc->fb == NULL) { 3420 if (crtc->fb == NULL) {
3420 /* The framebuffer is currently unbound, presumably 3421 /* The framebuffer is currently unbound, presumably
3421 * due to a hotplug event, that userspace has not 3422 * due to a hotplug event, that userspace has not
3422 * yet discovered. 3423 * yet discovered.
3423 */ 3424 */
3424 ret = -EBUSY; 3425 ret = -EBUSY;
3425 goto out; 3426 goto out;
3426 } 3427 }
3427 3428
3428 if (crtc->funcs->page_flip == NULL) 3429 if (crtc->funcs->page_flip == NULL)
3429 goto out; 3430 goto out;
3430 3431
3431 fb = drm_framebuffer_lookup(dev, page_flip->fb_id); 3432 fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
3432 if (!fb) 3433 if (!fb)
3433 goto out; 3434 goto out;
3434 3435
3435 hdisplay = crtc->mode.hdisplay; 3436 hdisplay = crtc->mode.hdisplay;
3436 vdisplay = crtc->mode.vdisplay; 3437 vdisplay = crtc->mode.vdisplay;
3437 3438
3438 if (crtc->invert_dimensions) 3439 if (crtc->invert_dimensions)
3439 swap(hdisplay, vdisplay); 3440 swap(hdisplay, vdisplay);
3440 3441
3441 if (hdisplay > fb->width || 3442 if (hdisplay > fb->width ||
3442 vdisplay > fb->height || 3443 vdisplay > fb->height ||
3443 crtc->x > fb->width - hdisplay || 3444 crtc->x > fb->width - hdisplay ||
3444 crtc->y > fb->height - vdisplay) { 3445 crtc->y > fb->height - vdisplay) {
3445 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n", 3446 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
3446 fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y, 3447 fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
3447 crtc->invert_dimensions ? " (inverted)" : ""); 3448 crtc->invert_dimensions ? " (inverted)" : "");
3448 ret = -ENOSPC; 3449 ret = -ENOSPC;
3449 goto out; 3450 goto out;
3450 } 3451 }
3451 3452
3452 if (crtc->fb->pixel_format != fb->pixel_format) { 3453 if (crtc->fb->pixel_format != fb->pixel_format) {
3453 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n"); 3454 DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
3454 ret = -EINVAL; 3455 ret = -EINVAL;
3455 goto out; 3456 goto out;
3456 } 3457 }
3457 3458
3458 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3459 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3459 ret = -ENOMEM; 3460 ret = -ENOMEM;
3460 spin_lock_irqsave(&dev->event_lock, flags); 3461 spin_lock_irqsave(&dev->event_lock, flags);
3461 if (file_priv->event_space < sizeof e->event) { 3462 if (file_priv->event_space < sizeof e->event) {
3462 spin_unlock_irqrestore(&dev->event_lock, flags); 3463 spin_unlock_irqrestore(&dev->event_lock, flags);
3463 goto out; 3464 goto out;
3464 } 3465 }
3465 file_priv->event_space -= sizeof e->event; 3466 file_priv->event_space -= sizeof e->event;
3466 spin_unlock_irqrestore(&dev->event_lock, flags); 3467 spin_unlock_irqrestore(&dev->event_lock, flags);
3467 3468
3468 e = kzalloc(sizeof *e, GFP_KERNEL); 3469 e = kzalloc(sizeof *e, GFP_KERNEL);
3469 if (e == NULL) { 3470 if (e == NULL) {
3470 spin_lock_irqsave(&dev->event_lock, flags); 3471 spin_lock_irqsave(&dev->event_lock, flags);
3471 file_priv->event_space += sizeof e->event; 3472 file_priv->event_space += sizeof e->event;
3472 spin_unlock_irqrestore(&dev->event_lock, flags); 3473 spin_unlock_irqrestore(&dev->event_lock, flags);
3473 goto out; 3474 goto out;
3474 } 3475 }
3475 3476
3476 e->event.base.type = DRM_EVENT_FLIP_COMPLETE; 3477 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
3477 e->event.base.length = sizeof e->event; 3478 e->event.base.length = sizeof e->event;
3478 e->event.user_data = page_flip->user_data; 3479 e->event.user_data = page_flip->user_data;
3479 e->base.event = &e->event.base; 3480 e->base.event = &e->event.base;
3480 e->base.file_priv = file_priv; 3481 e->base.file_priv = file_priv;
3481 e->base.destroy = 3482 e->base.destroy =
3482 (void (*) (struct drm_pending_event *)) kfree; 3483 (void (*) (struct drm_pending_event *)) kfree;
3483 } 3484 }
3484 3485
3485 old_fb = crtc->fb; 3486 old_fb = crtc->fb;
3486 ret = crtc->funcs->page_flip(crtc, fb, e); 3487 ret = crtc->funcs->page_flip(crtc, fb, e);
3487 if (ret) { 3488 if (ret) {
3488 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) { 3489 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3489 spin_lock_irqsave(&dev->event_lock, flags); 3490 spin_lock_irqsave(&dev->event_lock, flags);
3490 file_priv->event_space += sizeof e->event; 3491 file_priv->event_space += sizeof e->event;
3491 spin_unlock_irqrestore(&dev->event_lock, flags); 3492 spin_unlock_irqrestore(&dev->event_lock, flags);
3492 kfree(e); 3493 kfree(e);
3493 } 3494 }
3494 /* Keep the old fb, don't unref it. */ 3495 /* Keep the old fb, don't unref it. */
3495 old_fb = NULL; 3496 old_fb = NULL;
3496 } else { 3497 } else {
3497 /* 3498 /*
3498 * Warn if the driver hasn't properly updated the crtc->fb 3499 * Warn if the driver hasn't properly updated the crtc->fb
3499 * field to reflect that the new framebuffer is now used. 3500 * field to reflect that the new framebuffer is now used.
3500 * Failing to do so will screw with the reference counting 3501 * Failing to do so will screw with the reference counting
3501 * on framebuffers. 3502 * on framebuffers.
3502 */ 3503 */
3503 WARN_ON(crtc->fb != fb); 3504 WARN_ON(crtc->fb != fb);
3504 /* Unref only the old framebuffer. */ 3505 /* Unref only the old framebuffer. */
3505 fb = NULL; 3506 fb = NULL;
3506 } 3507 }
3507 3508
3508 out: 3509 out:
3509 if (fb) 3510 if (fb)
3510 drm_framebuffer_unreference(fb); 3511 drm_framebuffer_unreference(fb);
3511 if (old_fb) 3512 if (old_fb)
3512 drm_framebuffer_unreference(old_fb); 3513 drm_framebuffer_unreference(old_fb);
3513 mutex_unlock(&crtc->mutex); 3514 mutex_unlock(&crtc->mutex);
3514 3515
3515 return ret; 3516 return ret;
3516 } 3517 }
3517 3518
3518 void drm_mode_config_reset(struct drm_device *dev) 3519 void drm_mode_config_reset(struct drm_device *dev)
3519 { 3520 {
3520 struct drm_crtc *crtc; 3521 struct drm_crtc *crtc;
3521 struct drm_encoder *encoder; 3522 struct drm_encoder *encoder;
3522 struct drm_connector *connector; 3523 struct drm_connector *connector;
3523 3524
3524 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 3525 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
3525 if (crtc->funcs->reset) 3526 if (crtc->funcs->reset)
3526 crtc->funcs->reset(crtc); 3527 crtc->funcs->reset(crtc);
3527 3528
3528 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 3529 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
3529 if (encoder->funcs->reset) 3530 if (encoder->funcs->reset)
3530 encoder->funcs->reset(encoder); 3531 encoder->funcs->reset(encoder);
3531 3532
3532 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 3533 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
3533 connector->status = connector_status_unknown; 3534 connector->status = connector_status_unknown;
3534 3535
3535 if (connector->funcs->reset) 3536 if (connector->funcs->reset)
3536 connector->funcs->reset(connector); 3537 connector->funcs->reset(connector);
3537 } 3538 }
3538 } 3539 }
3539 EXPORT_SYMBOL(drm_mode_config_reset); 3540 EXPORT_SYMBOL(drm_mode_config_reset);
3540 3541
3541 int drm_mode_create_dumb_ioctl(struct drm_device *dev, 3542 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
3542 void *data, struct drm_file *file_priv) 3543 void *data, struct drm_file *file_priv)
3543 { 3544 {
3544 struct drm_mode_create_dumb *args = data; 3545 struct drm_mode_create_dumb *args = data;
3545 3546
3546 if (!dev->driver->dumb_create) 3547 if (!dev->driver->dumb_create)
3547 return -ENOSYS; 3548 return -ENOSYS;
3548 return dev->driver->dumb_create(file_priv, dev, args); 3549 return dev->driver->dumb_create(file_priv, dev, args);
3549 } 3550 }
3550 3551
3551 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev, 3552 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
3552 void *data, struct drm_file *file_priv) 3553 void *data, struct drm_file *file_priv)
3553 { 3554 {
3554 struct drm_mode_map_dumb *args = data; 3555 struct drm_mode_map_dumb *args = data;
3555 3556
3556 /* call driver ioctl to get mmap offset */ 3557 /* call driver ioctl to get mmap offset */
3557 if (!dev->driver->dumb_map_offset) 3558 if (!dev->driver->dumb_map_offset)
3558 return -ENOSYS; 3559 return -ENOSYS;
3559 3560
3560 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset); 3561 return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
3561 } 3562 }
3562 3563
3563 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev, 3564 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
3564 void *data, struct drm_file *file_priv) 3565 void *data, struct drm_file *file_priv)
3565 { 3566 {
3566 struct drm_mode_destroy_dumb *args = data; 3567 struct drm_mode_destroy_dumb *args = data;
3567 3568
3568 if (!dev->driver->dumb_destroy) 3569 if (!dev->driver->dumb_destroy)
3569 return -ENOSYS; 3570 return -ENOSYS;
3570 3571
3571 return dev->driver->dumb_destroy(file_priv, dev, args->handle); 3572 return dev->driver->dumb_destroy(file_priv, dev, args->handle);
3572 } 3573 }
3573 3574
3574 /* 3575 /*
3575 * Just need to support RGB formats here for compat with code that doesn't 3576 * Just need to support RGB formats here for compat with code that doesn't
3576 * use pixel formats directly yet. 3577 * use pixel formats directly yet.
3577 */ 3578 */
3578 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, 3579 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
3579 int *bpp) 3580 int *bpp)
3580 { 3581 {
3581 switch (format) { 3582 switch (format) {
3582 case DRM_FORMAT_C8: 3583 case DRM_FORMAT_C8:
3583 case DRM_FORMAT_RGB332: 3584 case DRM_FORMAT_RGB332:
3584 case DRM_FORMAT_BGR233: 3585 case DRM_FORMAT_BGR233:
3585 *depth = 8; 3586 *depth = 8;
3586 *bpp = 8; 3587 *bpp = 8;
3587 break; 3588 break;
3588 case DRM_FORMAT_XRGB1555: 3589 case DRM_FORMAT_XRGB1555:
3589 case DRM_FORMAT_XBGR1555: 3590 case DRM_FORMAT_XBGR1555:
3590 case DRM_FORMAT_RGBX5551: 3591 case DRM_FORMAT_RGBX5551:
3591 case DRM_FORMAT_BGRX5551: 3592 case DRM_FORMAT_BGRX5551:
3592 case DRM_FORMAT_ARGB1555: 3593 case DRM_FORMAT_ARGB1555:
3593 case DRM_FORMAT_ABGR1555: 3594 case DRM_FORMAT_ABGR1555:
3594 case DRM_FORMAT_RGBA5551: 3595 case DRM_FORMAT_RGBA5551:
3595 case DRM_FORMAT_BGRA5551: 3596 case DRM_FORMAT_BGRA5551:
3596 *depth = 15; 3597 *depth = 15;
3597 *bpp = 16; 3598 *bpp = 16;
3598 break; 3599 break;
3599 case DRM_FORMAT_RGB565: 3600 case DRM_FORMAT_RGB565:
3600 case DRM_FORMAT_BGR565: 3601 case DRM_FORMAT_BGR565:
3601 *depth = 16; 3602 *depth = 16;
3602 *bpp = 16; 3603 *bpp = 16;
3603 break; 3604 break;
3604 case DRM_FORMAT_RGB888: 3605 case DRM_FORMAT_RGB888:
3605 case DRM_FORMAT_BGR888: 3606 case DRM_FORMAT_BGR888:
3606 *depth = 24; 3607 *depth = 24;
3607 *bpp = 24; 3608 *bpp = 24;
3608 break; 3609 break;
3609 case DRM_FORMAT_XRGB8888: 3610 case DRM_FORMAT_XRGB8888:
3610 case DRM_FORMAT_XBGR8888: 3611 case DRM_FORMAT_XBGR8888:
3611 case DRM_FORMAT_RGBX8888: 3612 case DRM_FORMAT_RGBX8888:
3612 case DRM_FORMAT_BGRX8888: 3613 case DRM_FORMAT_BGRX8888:
3613 *depth = 24; 3614 *depth = 24;
3614 *bpp = 32; 3615 *bpp = 32;
3615 break; 3616 break;
3616 case DRM_FORMAT_XRGB2101010: 3617 case DRM_FORMAT_XRGB2101010:
3617 case DRM_FORMAT_XBGR2101010: 3618 case DRM_FORMAT_XBGR2101010:
3618 case DRM_FORMAT_RGBX1010102: 3619 case DRM_FORMAT_RGBX1010102:
3619 case DRM_FORMAT_BGRX1010102: 3620 case DRM_FORMAT_BGRX1010102:
3620 case DRM_FORMAT_ARGB2101010: 3621 case DRM_FORMAT_ARGB2101010:
3621 case DRM_FORMAT_ABGR2101010: 3622 case DRM_FORMAT_ABGR2101010:
3622 case DRM_FORMAT_RGBA1010102: 3623 case DRM_FORMAT_RGBA1010102:
3623 case DRM_FORMAT_BGRA1010102: 3624 case DRM_FORMAT_BGRA1010102:
3624 *depth = 30; 3625 *depth = 30;
3625 *bpp = 32; 3626 *bpp = 32;
3626 break; 3627 break;
3627 case DRM_FORMAT_ARGB8888: 3628 case DRM_FORMAT_ARGB8888:
3628 case DRM_FORMAT_ABGR8888: 3629 case DRM_FORMAT_ABGR8888:
3629 case DRM_FORMAT_RGBA8888: 3630 case DRM_FORMAT_RGBA8888:
3630 case DRM_FORMAT_BGRA8888: 3631 case DRM_FORMAT_BGRA8888:
3631 *depth = 32; 3632 *depth = 32;
3632 *bpp = 32; 3633 *bpp = 32;
3633 break; 3634 break;
3634 default: 3635 default:
3635 DRM_DEBUG_KMS("unsupported pixel format\n"); 3636 DRM_DEBUG_KMS("unsupported pixel format\n");
3636 *depth = 0; 3637 *depth = 0;
3637 *bpp = 0; 3638 *bpp = 0;
3638 break; 3639 break;
3639 } 3640 }
3640 } 3641 }
3641 EXPORT_SYMBOL(drm_fb_get_bpp_depth); 3642 EXPORT_SYMBOL(drm_fb_get_bpp_depth);
3642 3643
3643 /** 3644 /**
3644 * drm_format_num_planes - get the number of planes for format 3645 * drm_format_num_planes - get the number of planes for format
3645 * @format: pixel format (DRM_FORMAT_*) 3646 * @format: pixel format (DRM_FORMAT_*)
3646 * 3647 *
3647 * RETURNS: 3648 * RETURNS:
3648 * The number of planes used by the specified pixel format. 3649 * The number of planes used by the specified pixel format.
3649 */ 3650 */
3650 int drm_format_num_planes(uint32_t format) 3651 int drm_format_num_planes(uint32_t format)
3651 { 3652 {
3652 switch (format) { 3653 switch (format) {
3653 case DRM_FORMAT_YUV410: 3654 case DRM_FORMAT_YUV410:
3654 case DRM_FORMAT_YVU410: 3655 case DRM_FORMAT_YVU410:
3655 case DRM_FORMAT_YUV411: 3656 case DRM_FORMAT_YUV411:
3656 case DRM_FORMAT_YVU411: 3657 case DRM_FORMAT_YVU411:
3657 case DRM_FORMAT_YUV420: 3658 case DRM_FORMAT_YUV420:
3658 case DRM_FORMAT_YVU420: 3659 case DRM_FORMAT_YVU420:
3659 case DRM_FORMAT_YUV422: 3660 case DRM_FORMAT_YUV422:
3660 case DRM_FORMAT_YVU422: 3661 case DRM_FORMAT_YVU422:
3661 case DRM_FORMAT_YUV444: 3662 case DRM_FORMAT_YUV444:
3662 case DRM_FORMAT_YVU444: 3663 case DRM_FORMAT_YVU444:
3663 return 3; 3664 return 3;
3664 case DRM_FORMAT_NV12: 3665 case DRM_FORMAT_NV12:
3665 case DRM_FORMAT_NV21: 3666 case DRM_FORMAT_NV21:
3666 case DRM_FORMAT_NV16: 3667 case DRM_FORMAT_NV16:
3667 case DRM_FORMAT_NV61: 3668 case DRM_FORMAT_NV61:
3668 case DRM_FORMAT_NV24: 3669 case DRM_FORMAT_NV24:
3669 case DRM_FORMAT_NV42: 3670 case DRM_FORMAT_NV42:
3670 return 2; 3671 return 2;
3671 default: 3672 default:
3672 return 1; 3673 return 1;
3673 } 3674 }
3674 } 3675 }
3675 EXPORT_SYMBOL(drm_format_num_planes); 3676 EXPORT_SYMBOL(drm_format_num_planes);
3676 3677
3677 /** 3678 /**
3678 * drm_format_plane_cpp - determine the bytes per pixel value 3679 * drm_format_plane_cpp - determine the bytes per pixel value
3679 * @format: pixel format (DRM_FORMAT_*) 3680 * @format: pixel format (DRM_FORMAT_*)
3680 * @plane: plane index 3681 * @plane: plane index
3681 * 3682 *
3682 * RETURNS: 3683 * RETURNS:
3683 * The bytes per pixel value for the specified plane. 3684 * The bytes per pixel value for the specified plane.
3684 */ 3685 */
3685 int drm_format_plane_cpp(uint32_t format, int plane) 3686 int drm_format_plane_cpp(uint32_t format, int plane)
3686 { 3687 {
3687 unsigned int depth; 3688 unsigned int depth;
3688 int bpp; 3689 int bpp;
3689 3690
3690 if (plane >= drm_format_num_planes(format)) 3691 if (plane >= drm_format_num_planes(format))
3691 return 0; 3692 return 0;
3692 3693
3693 switch (format) { 3694 switch (format) {
3694 case DRM_FORMAT_YUYV: 3695 case DRM_FORMAT_YUYV:
3695 case DRM_FORMAT_YVYU: 3696 case DRM_FORMAT_YVYU:
3696 case DRM_FORMAT_UYVY: 3697 case DRM_FORMAT_UYVY:
3697 case DRM_FORMAT_VYUY: 3698 case DRM_FORMAT_VYUY:
3698 return 2; 3699 return 2;
3699 case DRM_FORMAT_NV12: 3700 case DRM_FORMAT_NV12:
3700 case DRM_FORMAT_NV21: 3701 case DRM_FORMAT_NV21:
3701 case DRM_FORMAT_NV16: 3702 case DRM_FORMAT_NV16:
3702 case DRM_FORMAT_NV61: 3703 case DRM_FORMAT_NV61:
3703 case DRM_FORMAT_NV24: 3704 case DRM_FORMAT_NV24:
3704 case DRM_FORMAT_NV42: 3705 case DRM_FORMAT_NV42:
3705 return plane ? 2 : 1; 3706 return plane ? 2 : 1;
3706 case DRM_FORMAT_YUV410: 3707 case DRM_FORMAT_YUV410:
3707 case DRM_FORMAT_YVU410: 3708 case DRM_FORMAT_YVU410:
3708 case DRM_FORMAT_YUV411: 3709 case DRM_FORMAT_YUV411:
3709 case DRM_FORMAT_YVU411: 3710 case DRM_FORMAT_YVU411:
3710 case DRM_FORMAT_YUV420: 3711 case DRM_FORMAT_YUV420:
3711 case DRM_FORMAT_YVU420: 3712 case DRM_FORMAT_YVU420:
3712 case DRM_FORMAT_YUV422: 3713 case DRM_FORMAT_YUV422:
3713 case DRM_FORMAT_YVU422: 3714 case DRM_FORMAT_YVU422:
3714 case DRM_FORMAT_YUV444: 3715 case DRM_FORMAT_YUV444:
3715 case DRM_FORMAT_YVU444: 3716 case DRM_FORMAT_YVU444:
3716 return 1; 3717 return 1;
3717 default: 3718 default:
3718 drm_fb_get_bpp_depth(format, &depth, &bpp); 3719 drm_fb_get_bpp_depth(format, &depth, &bpp);
3719 return bpp >> 3; 3720 return bpp >> 3;
3720 } 3721 }
3721 } 3722 }
3722 EXPORT_SYMBOL(drm_format_plane_cpp); 3723 EXPORT_SYMBOL(drm_format_plane_cpp);
3723 3724
3724 /** 3725 /**
3725 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor 3726 * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
3726 * @format: pixel format (DRM_FORMAT_*) 3727 * @format: pixel format (DRM_FORMAT_*)
3727 * 3728 *
3728 * RETURNS: 3729 * RETURNS:
3729 * The horizontal chroma subsampling factor for the 3730 * The horizontal chroma subsampling factor for the
3730 * specified pixel format. 3731 * specified pixel format.
3731 */ 3732 */
3732 int drm_format_horz_chroma_subsampling(uint32_t format) 3733 int drm_format_horz_chroma_subsampling(uint32_t format)
3733 { 3734 {
3734 switch (format) { 3735 switch (format) {
3735 case DRM_FORMAT_YUV411: 3736 case DRM_FORMAT_YUV411:
3736 case DRM_FORMAT_YVU411: 3737 case DRM_FORMAT_YVU411:
3737 case DRM_FORMAT_YUV410: 3738 case DRM_FORMAT_YUV410:
3738 case DRM_FORMAT_YVU410: 3739 case DRM_FORMAT_YVU410:
3739 return 4; 3740 return 4;
3740 case DRM_FORMAT_YUYV: 3741 case DRM_FORMAT_YUYV:
3741 case DRM_FORMAT_YVYU: 3742 case DRM_FORMAT_YVYU:
3742 case DRM_FORMAT_UYVY: 3743 case DRM_FORMAT_UYVY:
3743 case DRM_FORMAT_VYUY: 3744 case DRM_FORMAT_VYUY:
3744 case DRM_FORMAT_NV12: 3745 case DRM_FORMAT_NV12:
3745 case DRM_FORMAT_NV21: 3746 case DRM_FORMAT_NV21:
3746 case DRM_FORMAT_NV16: 3747 case DRM_FORMAT_NV16:
3747 case DRM_FORMAT_NV61: 3748 case DRM_FORMAT_NV61:
3748 case DRM_FORMAT_YUV422: 3749 case DRM_FORMAT_YUV422:
3749 case DRM_FORMAT_YVU422: 3750 case DRM_FORMAT_YVU422:
3750 case DRM_FORMAT_YUV420: 3751 case DRM_FORMAT_YUV420:
3751 case DRM_FORMAT_YVU420: 3752 case DRM_FORMAT_YVU420:
3752 return 2; 3753 return 2;
3753 default: 3754 default:
3754 return 1; 3755 return 1;
3755 } 3756 }
3756 } 3757 }
3757 EXPORT_SYMBOL(drm_format_horz_chroma_subsampling); 3758 EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
3758 3759
3759 /** 3760 /**
3760 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor 3761 * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
3761 * @format: pixel format (DRM_FORMAT_*) 3762 * @format: pixel format (DRM_FORMAT_*)
3762 * 3763 *
3763 * RETURNS: 3764 * RETURNS:
3764 * The vertical chroma subsampling factor for the 3765 * The vertical chroma subsampling factor for the
3765 * specified pixel format. 3766 * specified pixel format.
3766 */ 3767 */
3767 int drm_format_vert_chroma_subsampling(uint32_t format) 3768 int drm_format_vert_chroma_subsampling(uint32_t format)
3768 { 3769 {
3769 switch (format) { 3770 switch (format) {
3770 case DRM_FORMAT_YUV410: 3771 case DRM_FORMAT_YUV410:
3771 case DRM_FORMAT_YVU410: 3772 case DRM_FORMAT_YVU410:
3772 return 4; 3773 return 4;
3773 case DRM_FORMAT_YUV420: 3774 case DRM_FORMAT_YUV420:
3774 case DRM_FORMAT_YVU420: 3775 case DRM_FORMAT_YVU420:
3775 case DRM_FORMAT_NV12: 3776 case DRM_FORMAT_NV12:
3776 case DRM_FORMAT_NV21: 3777 case DRM_FORMAT_NV21:
3777 return 2; 3778 return 2;
3778 default: 3779 default:
3779 return 1; 3780 return 1;
3780 } 3781 }
3781 } 3782 }
3782 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling); 3783 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
3783 3784
3784 /** 3785 /**
3785 * drm_mode_config_init - initialize DRM mode_configuration structure 3786 * drm_mode_config_init - initialize DRM mode_configuration structure
3786 * @dev: DRM device 3787 * @dev: DRM device
3787 * 3788 *
3788 * Initialize @dev's mode_config structure, used for tracking the graphics 3789 * Initialize @dev's mode_config structure, used for tracking the graphics
3789 * configuration of @dev. 3790 * configuration of @dev.
3790 * 3791 *
3791 * Since this initializes the modeset locks, no locking is possible. Which is no 3792 * Since this initializes the modeset locks, no locking is possible. Which is no
3792 * problem, since this should happen single threaded at init time. It is the 3793 * problem, since this should happen single threaded at init time. It is the
3793 * driver's problem to ensure this guarantee. 3794 * driver's problem to ensure this guarantee.
3794 * 3795 *
3795 */ 3796 */
3796 void drm_mode_config_init(struct drm_device *dev) 3797 void drm_mode_config_init(struct drm_device *dev)
3797 { 3798 {
3798 mutex_init(&dev->mode_config.mutex); 3799 mutex_init(&dev->mode_config.mutex);
3799 mutex_init(&dev->mode_config.idr_mutex); 3800 mutex_init(&dev->mode_config.idr_mutex);
3800 mutex_init(&dev->mode_config.fb_lock); 3801 mutex_init(&dev->mode_config.fb_lock);
3801 INIT_LIST_HEAD(&dev->mode_config.fb_list); 3802 INIT_LIST_HEAD(&dev->mode_config.fb_list);
3802 INIT_LIST_HEAD(&dev->mode_config.crtc_list); 3803 INIT_LIST_HEAD(&dev->mode_config.crtc_list);
3803 INIT_LIST_HEAD(&dev->mode_config.connector_list); 3804 INIT_LIST_HEAD(&dev->mode_config.connector_list);
3804 INIT_LIST_HEAD(&dev->mode_config.encoder_list); 3805 INIT_LIST_HEAD(&dev->mode_config.encoder_list);
3805 INIT_LIST_HEAD(&dev->mode_config.property_list); 3806 INIT_LIST_HEAD(&dev->mode_config.property_list);
3806 INIT_LIST_HEAD(&dev->mode_config.property_blob_list); 3807 INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
3807 INIT_LIST_HEAD(&dev->mode_config.plane_list); 3808 INIT_LIST_HEAD(&dev->mode_config.plane_list);
3808 idr_init(&dev->mode_config.crtc_idr); 3809 idr_init(&dev->mode_config.crtc_idr);
3809 3810
3810 drm_modeset_lock_all(dev); 3811 drm_modeset_lock_all(dev);
3811 drm_mode_create_standard_connector_properties(dev); 3812 drm_mode_create_standard_connector_properties(dev);
3812 drm_modeset_unlock_all(dev); 3813 drm_modeset_unlock_all(dev);
3813 3814
3814 /* Just to be sure */ 3815 /* Just to be sure */
3815 dev->mode_config.num_fb = 0; 3816 dev->mode_config.num_fb = 0;
3816 dev->mode_config.num_connector = 0; 3817 dev->mode_config.num_connector = 0;
3817 dev->mode_config.num_crtc = 0; 3818 dev->mode_config.num_crtc = 0;
3818 dev->mode_config.num_encoder = 0; 3819 dev->mode_config.num_encoder = 0;
3819 } 3820 }
3820 EXPORT_SYMBOL(drm_mode_config_init); 3821 EXPORT_SYMBOL(drm_mode_config_init);
3821 3822
3822 /** 3823 /**
3823 * drm_mode_config_cleanup - free up DRM mode_config info 3824 * drm_mode_config_cleanup - free up DRM mode_config info
3824 * @dev: DRM device 3825 * @dev: DRM device
3825 * 3826 *
3826 * Free up all the connectors and CRTCs associated with this DRM device, then 3827 * Free up all the connectors and CRTCs associated with this DRM device, then
3827 * free up the framebuffers and associated buffer objects. 3828 * free up the framebuffers and associated buffer objects.
3828 * 3829 *
3829 * Note that since this /should/ happen single-threaded at driver/device 3830 * Note that since this /should/ happen single-threaded at driver/device
3830 * teardown time, no locking is required. It's the driver's job to ensure that 3831 * teardown time, no locking is required. It's the driver's job to ensure that
3831 * this guarantee actually holds true. 3832 * this guarantee actually holds true.
3832 * 3833 *
3833 * FIXME: cleanup any dangling user buffer objects too 3834 * FIXME: cleanup any dangling user buffer objects too
3834 */ 3835 */
3835 void drm_mode_config_cleanup(struct drm_device *dev) 3836 void drm_mode_config_cleanup(struct drm_device *dev)
3836 { 3837 {
3837 struct drm_connector *connector, *ot; 3838 struct drm_connector *connector, *ot;
3838 struct drm_crtc *crtc, *ct; 3839 struct drm_crtc *crtc, *ct;
3839 struct drm_encoder *encoder, *enct; 3840 struct drm_encoder *encoder, *enct;
3840 struct drm_framebuffer *fb, *fbt; 3841 struct drm_framebuffer *fb, *fbt;
3841 struct drm_property *property, *pt; 3842 struct drm_property *property, *pt;
3842 struct drm_property_blob *blob, *bt; 3843 struct drm_property_blob *blob, *bt;
3843 struct drm_plane *plane, *plt; 3844 struct drm_plane *plane, *plt;
3844 3845
3845 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list, 3846 list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
3846 head) { 3847 head) {
3847 encoder->funcs->destroy(encoder); 3848 encoder->funcs->destroy(encoder);
3848 } 3849 }
3849 3850
3850 list_for_each_entry_safe(connector, ot, 3851 list_for_each_entry_safe(connector, ot,
3851 &dev->mode_config.connector_list, head) { 3852 &dev->mode_config.connector_list, head) {
3852 connector->funcs->destroy(connector); 3853 connector->funcs->destroy(connector);
3853 } 3854 }
3854 3855
3855 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list, 3856 list_for_each_entry_safe(property, pt, &dev->mode_config.property_list,
3856 head) { 3857 head) {
3857 drm_property_destroy(dev, property); 3858 drm_property_destroy(dev, property);
3858 } 3859 }
3859 3860
3860 list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list, 3861 list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
3861 head) { 3862 head) {
3862 drm_property_destroy_blob(dev, blob); 3863 drm_property_destroy_blob(dev, blob);
3863 } 3864 }
3864 3865
3865 /* 3866 /*
3866 * Single-threaded teardown context, so it's not required to grab the 3867 * Single-threaded teardown context, so it's not required to grab the
3867 * fb_lock to protect against concurrent fb_list access. Contrary, it 3868 * fb_lock to protect against concurrent fb_list access. Contrary, it
3868 * would actually deadlock with the drm_framebuffer_cleanup function. 3869 * would actually deadlock with the drm_framebuffer_cleanup function.
3869 * 3870 *
3870 * Also, if there are any framebuffers left, that's a driver leak now, 3871 * Also, if there are any framebuffers left, that's a driver leak now,
3871 * so politely WARN about this. 3872 * so politely WARN about this.
3872 */ 3873 */
3873 WARN_ON(!list_empty(&dev->mode_config.fb_list)); 3874 WARN_ON(!list_empty(&dev->mode_config.fb_list));
3874 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) { 3875 list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
3875 drm_framebuffer_remove(fb); 3876 drm_framebuffer_remove(fb);
3876 } 3877 }
3877 3878
3878 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, 3879 list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list,
3879 head) { 3880 head) {
3880 plane->funcs->destroy(plane); 3881 plane->funcs->destroy(plane);
3881 } 3882 }
3882 3883
3883 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { 3884 list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
3884 crtc->funcs->destroy(crtc); 3885 crtc->funcs->destroy(crtc);
3885 } 3886 }
3886 3887
3887 idr_destroy(&dev->mode_config.crtc_idr); 3888 idr_destroy(&dev->mode_config.crtc_idr);
3888 } 3889 }
3889 EXPORT_SYMBOL(drm_mode_config_cleanup); 3890 EXPORT_SYMBOL(drm_mode_config_cleanup);
3890 3891
drivers/gpu/drm/drm_crtc_helper.c
1 /* 1 /*
2 * Copyright (c) 2006-2008 Intel Corporation 2 * Copyright (c) 2006-2008 Intel Corporation
3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie> 3 * Copyright (c) 2007 Dave Airlie <airlied@linux.ie>
4 * 4 *
5 * DRM core CRTC related functions 5 * DRM core CRTC related functions
6 * 6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its 7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that 8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright 9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation, and 10 * notice and this permission notice appear in supporting documentation, and
11 * that the name of the copyright holders not be used in advertising or 11 * that the name of the copyright holders not be used in advertising or
12 * publicity pertaining to distribution of the software without specific, 12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission. The copyright holders make no representations 13 * written prior permission. The copyright holders make no representations
14 * about the suitability of this software for any purpose. It is provided "as 14 * about the suitability of this software for any purpose. It is provided "as
15 * is" without express or implied warranty. 15 * is" without express or implied warranty.
16 * 16 *
17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 17 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 19 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * OF THIS SOFTWARE. 23 * OF THIS SOFTWARE.
24 * 24 *
25 * Authors: 25 * Authors:
26 * Keith Packard 26 * Keith Packard
27 * Eric Anholt <eric@anholt.net> 27 * Eric Anholt <eric@anholt.net>
28 * Dave Airlie <airlied@linux.ie> 28 * Dave Airlie <airlied@linux.ie>
29 * Jesse Barnes <jesse.barnes@intel.com> 29 * Jesse Barnes <jesse.barnes@intel.com>
30 */ 30 */
31 31
32 #include <linux/export.h> 32 #include <linux/export.h>
33 #include <linux/moduleparam.h> 33 #include <linux/moduleparam.h>
34 34
35 #include <drm/drmP.h> 35 #include <drm/drmP.h>
36 #include <drm/drm_crtc.h> 36 #include <drm/drm_crtc.h>
37 #include <drm/drm_fourcc.h> 37 #include <drm/drm_fourcc.h>
38 #include <drm/drm_crtc_helper.h> 38 #include <drm/drm_crtc_helper.h>
39 #include <drm/drm_fb_helper.h> 39 #include <drm/drm_fb_helper.h>
40 #include <drm/drm_edid.h> 40 #include <drm/drm_edid.h>
41 41
42 /** 42 /**
43 * drm_helper_move_panel_connectors_to_head() - move panels to the front in the 43 * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
44 * connector list 44 * connector list
45 * @dev: drm device to operate on 45 * @dev: drm device to operate on
46 * 46 *
47 * Some userspace presumes that the first connected connector is the main 47 * Some userspace presumes that the first connected connector is the main
48 * display, where it's supposed to display e.g. the login screen. For 48 * display, where it's supposed to display e.g. the login screen. For
49 * laptops, this should be the main panel. Use this function to sort all 49 * laptops, this should be the main panel. Use this function to sort all
50 * (eDP/LVDS) panels to the front of the connector list, instead of 50 * (eDP/LVDS) panels to the front of the connector list, instead of
51 * painstakingly trying to initialize them in the right order. 51 * painstakingly trying to initialize them in the right order.
52 */ 52 */
53 void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) 53 void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
54 { 54 {
55 struct drm_connector *connector, *tmp; 55 struct drm_connector *connector, *tmp;
56 struct list_head panel_list; 56 struct list_head panel_list;
57 57
58 INIT_LIST_HEAD(&panel_list); 58 INIT_LIST_HEAD(&panel_list);
59 59
60 list_for_each_entry_safe(connector, tmp, 60 list_for_each_entry_safe(connector, tmp,
61 &dev->mode_config.connector_list, head) { 61 &dev->mode_config.connector_list, head) {
62 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || 62 if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
63 connector->connector_type == DRM_MODE_CONNECTOR_eDP) 63 connector->connector_type == DRM_MODE_CONNECTOR_eDP)
64 list_move_tail(&connector->head, &panel_list); 64 list_move_tail(&connector->head, &panel_list);
65 } 65 }
66 66
67 list_splice(&panel_list, &dev->mode_config.connector_list); 67 list_splice(&panel_list, &dev->mode_config.connector_list);
68 } 68 }
69 EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); 69 EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
70 70
71 static bool drm_kms_helper_poll = true; 71 static bool drm_kms_helper_poll = true;
72 module_param_named(poll, drm_kms_helper_poll, bool, 0600); 72 module_param_named(poll, drm_kms_helper_poll, bool, 0600);
73 73
74 static void drm_mode_validate_flag(struct drm_connector *connector, 74 static void drm_mode_validate_flag(struct drm_connector *connector,
75 int flags) 75 int flags)
76 { 76 {
77 struct drm_display_mode *mode; 77 struct drm_display_mode *mode;
78 78
79 if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) 79 if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE))
80 return; 80 return;
81 81
82 list_for_each_entry(mode, &connector->modes, head) { 82 list_for_each_entry(mode, &connector->modes, head) {
83 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && 83 if ((mode->flags & DRM_MODE_FLAG_INTERLACE) &&
84 !(flags & DRM_MODE_FLAG_INTERLACE)) 84 !(flags & DRM_MODE_FLAG_INTERLACE))
85 mode->status = MODE_NO_INTERLACE; 85 mode->status = MODE_NO_INTERLACE;
86 if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && 86 if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) &&
87 !(flags & DRM_MODE_FLAG_DBLSCAN)) 87 !(flags & DRM_MODE_FLAG_DBLSCAN))
88 mode->status = MODE_NO_DBLESCAN; 88 mode->status = MODE_NO_DBLESCAN;
89 } 89 }
90 90
91 return; 91 return;
92 } 92 }
93 93
94 /** 94 /**
95 * drm_helper_probe_single_connector_modes - get complete set of display modes 95 * drm_helper_probe_single_connector_modes - get complete set of display modes
96 * @connector: connector to probe 96 * @connector: connector to probe
97 * @maxX: max width for modes 97 * @maxX: max width for modes
98 * @maxY: max height for modes 98 * @maxY: max height for modes
99 * 99 *
100 * LOCKING: 100 * LOCKING:
101 * Caller must hold mode config lock. 101 * Caller must hold mode config lock.
102 * 102 *
103 * Based on the helper callbacks implemented by @connector try to detect all 103 * Based on the helper callbacks implemented by @connector try to detect all
104 * valid modes. Modes will first be added to the connector's probed_modes list, 104 * valid modes. Modes will first be added to the connector's probed_modes list,
105 * then culled (based on validity and the @maxX, @maxY parameters) and put into 105 * then culled (based on validity and the @maxX, @maxY parameters) and put into
106 * the normal modes list. 106 * the normal modes list.
107 * 107 *
108 * Intended to be use as a generic implementation of the ->probe() @connector 108 * Intended to be use as a generic implementation of the ->probe() @connector
109 * callback for drivers that use the crtc helpers for output mode filtering and 109 * callback for drivers that use the crtc helpers for output mode filtering and
110 * detection. 110 * detection.
111 * 111 *
112 * RETURNS: 112 * RETURNS:
113 * Number of modes found on @connector. 113 * Number of modes found on @connector.
114 */ 114 */
115 int drm_helper_probe_single_connector_modes(struct drm_connector *connector, 115 int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
116 uint32_t maxX, uint32_t maxY) 116 uint32_t maxX, uint32_t maxY)
117 { 117 {
118 struct drm_device *dev = connector->dev; 118 struct drm_device *dev = connector->dev;
119 struct drm_display_mode *mode; 119 struct drm_display_mode *mode;
120 struct drm_connector_helper_funcs *connector_funcs = 120 struct drm_connector_helper_funcs *connector_funcs =
121 connector->helper_private; 121 connector->helper_private;
122 int count = 0; 122 int count = 0;
123 int mode_flags = 0; 123 int mode_flags = 0;
124 bool verbose_prune = true; 124 bool verbose_prune = true;
125 125
126 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, 126 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
127 drm_get_connector_name(connector)); 127 drm_get_connector_name(connector));
128 /* set all modes to the unverified state */ 128 /* set all modes to the unverified state */
129 list_for_each_entry(mode, &connector->modes, head) 129 list_for_each_entry(mode, &connector->modes, head)
130 mode->status = MODE_UNVERIFIED; 130 mode->status = MODE_UNVERIFIED;
131 131
132 if (connector->force) { 132 if (connector->force) {
133 if (connector->force == DRM_FORCE_ON) 133 if (connector->force == DRM_FORCE_ON)
134 connector->status = connector_status_connected; 134 connector->status = connector_status_connected;
135 else 135 else
136 connector->status = connector_status_disconnected; 136 connector->status = connector_status_disconnected;
137 if (connector->funcs->force) 137 if (connector->funcs->force)
138 connector->funcs->force(connector); 138 connector->funcs->force(connector);
139 } else { 139 } else {
140 connector->status = connector->funcs->detect(connector, true); 140 connector->status = connector->funcs->detect(connector, true);
141 } 141 }
142 142
143 /* Re-enable polling in case the global poll config changed. */ 143 /* Re-enable polling in case the global poll config changed. */
144 if (drm_kms_helper_poll != dev->mode_config.poll_running) 144 if (drm_kms_helper_poll != dev->mode_config.poll_running)
145 drm_kms_helper_poll_enable(dev); 145 drm_kms_helper_poll_enable(dev);
146 146
147 dev->mode_config.poll_running = drm_kms_helper_poll; 147 dev->mode_config.poll_running = drm_kms_helper_poll;
148 148
149 if (connector->status == connector_status_disconnected) { 149 if (connector->status == connector_status_disconnected) {
150 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", 150 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
151 connector->base.id, drm_get_connector_name(connector)); 151 connector->base.id, drm_get_connector_name(connector));
152 drm_mode_connector_update_edid_property(connector, NULL); 152 drm_mode_connector_update_edid_property(connector, NULL);
153 verbose_prune = false; 153 verbose_prune = false;
154 goto prune; 154 goto prune;
155 } 155 }
156 156
157 #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE 157 #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
158 count = drm_load_edid_firmware(connector); 158 count = drm_load_edid_firmware(connector);
159 if (count == 0) 159 if (count == 0)
160 #endif 160 #endif
161 count = (*connector_funcs->get_modes)(connector); 161 count = (*connector_funcs->get_modes)(connector);
162 162
163 if (count == 0 && connector->status == connector_status_connected) 163 if (count == 0 && connector->status == connector_status_connected)
164 count = drm_add_modes_noedid(connector, 1024, 768); 164 count = drm_add_modes_noedid(connector, 1024, 768);
165 if (count == 0) 165 if (count == 0)
166 goto prune; 166 goto prune;
167 167
168 drm_mode_connector_list_update(connector); 168 drm_mode_connector_list_update(connector);
169 169
170 if (maxX && maxY) 170 if (maxX && maxY)
171 drm_mode_validate_size(dev, &connector->modes, maxX, 171 drm_mode_validate_size(dev, &connector->modes, maxX,
172 maxY, 0); 172 maxY, 0);
173 173
174 if (connector->interlace_allowed) 174 if (connector->interlace_allowed)
175 mode_flags |= DRM_MODE_FLAG_INTERLACE; 175 mode_flags |= DRM_MODE_FLAG_INTERLACE;
176 if (connector->doublescan_allowed) 176 if (connector->doublescan_allowed)
177 mode_flags |= DRM_MODE_FLAG_DBLSCAN; 177 mode_flags |= DRM_MODE_FLAG_DBLSCAN;
178 drm_mode_validate_flag(connector, mode_flags); 178 drm_mode_validate_flag(connector, mode_flags);
179 179
180 list_for_each_entry(mode, &connector->modes, head) { 180 list_for_each_entry(mode, &connector->modes, head) {
181 if (mode->status == MODE_OK) 181 if (mode->status == MODE_OK)
182 mode->status = connector_funcs->mode_valid(connector, 182 mode->status = connector_funcs->mode_valid(connector,
183 mode); 183 mode);
184 } 184 }
185 185
186 prune: 186 prune:
187 drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); 187 drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);
188 188
189 if (list_empty(&connector->modes)) 189 if (list_empty(&connector->modes))
190 return 0; 190 return 0;
191 191
192 drm_mode_sort(&connector->modes); 192 drm_mode_sort(&connector->modes);
193 193
194 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, 194 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
195 drm_get_connector_name(connector)); 195 drm_get_connector_name(connector));
196 list_for_each_entry(mode, &connector->modes, head) { 196 list_for_each_entry(mode, &connector->modes, head) {
197 mode->vrefresh = drm_mode_vrefresh(mode); 197 mode->vrefresh = drm_mode_vrefresh(mode);
198 198
199 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 199 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
200 drm_mode_debug_printmodeline(mode); 200 drm_mode_debug_printmodeline(mode);
201 } 201 }
202 202
203 return count; 203 return count;
204 } 204 }
205 EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); 205 EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
206 206
207 /** 207 /**
208 * drm_helper_encoder_in_use - check if a given encoder is in use 208 * drm_helper_encoder_in_use - check if a given encoder is in use
209 * @encoder: encoder to check 209 * @encoder: encoder to check
210 * 210 *
211 * LOCKING: 211 * LOCKING:
212 * Caller must hold mode config lock. 212 * Caller must hold mode config lock.
213 * 213 *
214 * Walk @encoders's DRM device's mode_config and see if it's in use. 214 * Walk @encoders's DRM device's mode_config and see if it's in use.
215 * 215 *
216 * RETURNS: 216 * RETURNS:
217 * True if @encoder is part of the mode_config, false otherwise. 217 * True if @encoder is part of the mode_config, false otherwise.
218 */ 218 */
219 bool drm_helper_encoder_in_use(struct drm_encoder *encoder) 219 bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
220 { 220 {
221 struct drm_connector *connector; 221 struct drm_connector *connector;
222 struct drm_device *dev = encoder->dev; 222 struct drm_device *dev = encoder->dev;
223 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 223 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
224 if (connector->encoder == encoder) 224 if (connector->encoder == encoder)
225 return true; 225 return true;
226 return false; 226 return false;
227 } 227 }
228 EXPORT_SYMBOL(drm_helper_encoder_in_use); 228 EXPORT_SYMBOL(drm_helper_encoder_in_use);
229 229
230 /** 230 /**
231 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 231 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
232 * @crtc: CRTC to check 232 * @crtc: CRTC to check
233 * 233 *
234 * LOCKING: 234 * LOCKING:
235 * Caller must hold mode config lock. 235 * Caller must hold mode config lock.
236 * 236 *
237 * Walk @crtc's DRM device's mode_config and see if it's in use. 237 * Walk @crtc's DRM device's mode_config and see if it's in use.
238 * 238 *
239 * RETURNS: 239 * RETURNS:
240 * True if @crtc is part of the mode_config, false otherwise. 240 * True if @crtc is part of the mode_config, false otherwise.
241 */ 241 */
242 bool drm_helper_crtc_in_use(struct drm_crtc *crtc) 242 bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
243 { 243 {
244 struct drm_encoder *encoder; 244 struct drm_encoder *encoder;
245 struct drm_device *dev = crtc->dev; 245 struct drm_device *dev = crtc->dev;
246 /* FIXME: Locking around list access? */ 246 /* FIXME: Locking around list access? */
247 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) 247 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
248 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) 248 if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
249 return true; 249 return true;
250 return false; 250 return false;
251 } 251 }
252 EXPORT_SYMBOL(drm_helper_crtc_in_use); 252 EXPORT_SYMBOL(drm_helper_crtc_in_use);
253 253
254 static void 254 static void
255 drm_encoder_disable(struct drm_encoder *encoder) 255 drm_encoder_disable(struct drm_encoder *encoder)
256 { 256 {
257 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 257 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
258 258
259 if (encoder_funcs->disable) 259 if (encoder_funcs->disable)
260 (*encoder_funcs->disable)(encoder); 260 (*encoder_funcs->disable)(encoder);
261 else 261 else
262 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); 262 (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
263 } 263 }
264 264
265 /** 265 /**
266 * drm_helper_disable_unused_functions - disable unused objects 266 * drm_helper_disable_unused_functions - disable unused objects
267 * @dev: DRM device 267 * @dev: DRM device
268 * 268 *
269 * LOCKING: 269 * LOCKING:
270 * Caller must hold mode config lock. 270 * Caller must hold mode config lock.
271 * 271 *
272 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled 272 * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
273 * by calling its dpms function, which should power it off. 273 * by calling its dpms function, which should power it off.
274 */ 274 */
275 void drm_helper_disable_unused_functions(struct drm_device *dev) 275 void drm_helper_disable_unused_functions(struct drm_device *dev)
276 { 276 {
277 struct drm_encoder *encoder; 277 struct drm_encoder *encoder;
278 struct drm_connector *connector; 278 struct drm_connector *connector;
279 struct drm_crtc *crtc; 279 struct drm_crtc *crtc;
280 280
281 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 281 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
282 if (!connector->encoder) 282 if (!connector->encoder)
283 continue; 283 continue;
284 if (connector->status == connector_status_disconnected) 284 if (connector->status == connector_status_disconnected)
285 connector->encoder = NULL; 285 connector->encoder = NULL;
286 } 286 }
287 287
288 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 288 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
289 if (!drm_helper_encoder_in_use(encoder)) { 289 if (!drm_helper_encoder_in_use(encoder)) {
290 drm_encoder_disable(encoder); 290 drm_encoder_disable(encoder);
291 /* disconnector encoder from any connector */ 291 /* disconnector encoder from any connector */
292 encoder->crtc = NULL; 292 encoder->crtc = NULL;
293 } 293 }
294 } 294 }
295 295
296 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 296 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
297 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 297 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
298 crtc->enabled = drm_helper_crtc_in_use(crtc); 298 crtc->enabled = drm_helper_crtc_in_use(crtc);
299 if (!crtc->enabled) { 299 if (!crtc->enabled) {
300 if (crtc_funcs->disable) 300 if (crtc_funcs->disable)
301 (*crtc_funcs->disable)(crtc); 301 (*crtc_funcs->disable)(crtc);
302 else 302 else
303 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); 303 (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
304 crtc->fb = NULL; 304 crtc->fb = NULL;
305 } 305 }
306 } 306 }
307 } 307 }
308 EXPORT_SYMBOL(drm_helper_disable_unused_functions); 308 EXPORT_SYMBOL(drm_helper_disable_unused_functions);
309 309
310 /** 310 /**
311 * drm_encoder_crtc_ok - can a given crtc drive a given encoder? 311 * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
312 * @encoder: encoder to test 312 * @encoder: encoder to test
313 * @crtc: crtc to test 313 * @crtc: crtc to test
314 * 314 *
315 * Return false if @encoder can't be driven by @crtc, true otherwise. 315 * Return false if @encoder can't be driven by @crtc, true otherwise.
316 */ 316 */
317 static bool drm_encoder_crtc_ok(struct drm_encoder *encoder, 317 static bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
318 struct drm_crtc *crtc) 318 struct drm_crtc *crtc)
319 { 319 {
320 struct drm_device *dev; 320 struct drm_device *dev;
321 struct drm_crtc *tmp; 321 struct drm_crtc *tmp;
322 int crtc_mask = 1; 322 int crtc_mask = 1;
323 323
324 WARN(!crtc, "checking null crtc?\n"); 324 WARN(!crtc, "checking null crtc?\n");
325 325
326 dev = crtc->dev; 326 dev = crtc->dev;
327 327
328 list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) { 328 list_for_each_entry(tmp, &dev->mode_config.crtc_list, head) {
329 if (tmp == crtc) 329 if (tmp == crtc)
330 break; 330 break;
331 crtc_mask <<= 1; 331 crtc_mask <<= 1;
332 } 332 }
333 333
334 if (encoder->possible_crtcs & crtc_mask) 334 if (encoder->possible_crtcs & crtc_mask)
335 return true; 335 return true;
336 return false; 336 return false;
337 } 337 }
338 338
339 /* 339 /*
340 * Check the CRTC we're going to map each output to vs. its current 340 * Check the CRTC we're going to map each output to vs. its current
341 * CRTC. If they don't match, we have to disable the output and the CRTC 341 * CRTC. If they don't match, we have to disable the output and the CRTC
342 * since the driver will have to re-route things. 342 * since the driver will have to re-route things.
343 */ 343 */
344 static void 344 static void
345 drm_crtc_prepare_encoders(struct drm_device *dev) 345 drm_crtc_prepare_encoders(struct drm_device *dev)
346 { 346 {
347 struct drm_encoder_helper_funcs *encoder_funcs; 347 struct drm_encoder_helper_funcs *encoder_funcs;
348 struct drm_encoder *encoder; 348 struct drm_encoder *encoder;
349 349
350 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 350 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
351 encoder_funcs = encoder->helper_private; 351 encoder_funcs = encoder->helper_private;
352 /* Disable unused encoders */ 352 /* Disable unused encoders */
353 if (encoder->crtc == NULL) 353 if (encoder->crtc == NULL)
354 drm_encoder_disable(encoder); 354 drm_encoder_disable(encoder);
355 /* Disable encoders whose CRTC is about to change */ 355 /* Disable encoders whose CRTC is about to change */
356 if (encoder_funcs->get_crtc && 356 if (encoder_funcs->get_crtc &&
357 encoder->crtc != (*encoder_funcs->get_crtc)(encoder)) 357 encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
358 drm_encoder_disable(encoder); 358 drm_encoder_disable(encoder);
359 } 359 }
360 } 360 }
361 361
362 /** 362 /**
363 * drm_crtc_helper_set_mode - internal helper to set a mode 363 * drm_crtc_helper_set_mode - internal helper to set a mode
364 * @crtc: CRTC to program 364 * @crtc: CRTC to program
365 * @mode: mode to use 365 * @mode: mode to use
366 * @x: horizontal offset into the surface 366 * @x: horizontal offset into the surface
367 * @y: vertical offset into the surface 367 * @y: vertical offset into the surface
368 * @old_fb: old framebuffer, for cleanup 368 * @old_fb: old framebuffer, for cleanup
369 * 369 *
370 * LOCKING: 370 * LOCKING:
371 * Caller must hold mode config lock. 371 * Caller must hold mode config lock.
372 * 372 *
373 * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance 373 * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance
374 * to fixup or reject the mode prior to trying to set it. This is an internal 374 * to fixup or reject the mode prior to trying to set it. This is an internal
375 * helper that drivers could e.g. use to update properties that require the 375 * helper that drivers could e.g. use to update properties that require the
376 * entire output pipe to be disabled and re-enabled in a new configuration. For 376 * entire output pipe to be disabled and re-enabled in a new configuration. For
377 * example for changing whether audio is enabled on a hdmi link or for changing 377 * example for changing whether audio is enabled on a hdmi link or for changing
378 * panel fitter or dither attributes. It is also called by the 378 * panel fitter or dither attributes. It is also called by the
379 * drm_crtc_helper_set_config() helper function to drive the mode setting 379 * drm_crtc_helper_set_config() helper function to drive the mode setting
380 * sequence. 380 * sequence.
381 * 381 *
382 * RETURNS: 382 * RETURNS:
383 * True if the mode was set successfully, or false otherwise. 383 * True if the mode was set successfully, or false otherwise.
384 */ 384 */
385 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, 385 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
386 struct drm_display_mode *mode, 386 struct drm_display_mode *mode,
387 int x, int y, 387 int x, int y,
388 struct drm_framebuffer *old_fb) 388 struct drm_framebuffer *old_fb)
389 { 389 {
390 struct drm_device *dev = crtc->dev; 390 struct drm_device *dev = crtc->dev;
391 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; 391 struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode;
392 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 392 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
393 struct drm_encoder_helper_funcs *encoder_funcs; 393 struct drm_encoder_helper_funcs *encoder_funcs;
394 int saved_x, saved_y; 394 int saved_x, saved_y;
395 struct drm_encoder *encoder; 395 struct drm_encoder *encoder;
396 bool ret = true; 396 bool ret = true;
397 397
398 crtc->enabled = drm_helper_crtc_in_use(crtc); 398 crtc->enabled = drm_helper_crtc_in_use(crtc);
399 if (!crtc->enabled) 399 if (!crtc->enabled)
400 return true; 400 return true;
401 401
402 adjusted_mode = drm_mode_duplicate(dev, mode); 402 adjusted_mode = drm_mode_duplicate(dev, mode);
403 if (!adjusted_mode) 403 if (!adjusted_mode)
404 return false; 404 return false;
405 405
406 saved_hwmode = crtc->hwmode; 406 saved_hwmode = crtc->hwmode;
407 saved_mode = crtc->mode; 407 saved_mode = crtc->mode;
408 saved_x = crtc->x; 408 saved_x = crtc->x;
409 saved_y = crtc->y; 409 saved_y = crtc->y;
410 410
411 /* Update crtc values up front so the driver can rely on them for mode 411 /* Update crtc values up front so the driver can rely on them for mode
412 * setting. 412 * setting.
413 */ 413 */
414 crtc->mode = *mode; 414 crtc->mode = *mode;
415 crtc->x = x; 415 crtc->x = x;
416 crtc->y = y; 416 crtc->y = y;
417 417
418 /* Pass our mode to the connectors and the CRTC to give them a chance to 418 /* Pass our mode to the connectors and the CRTC to give them a chance to
419 * adjust it according to limitations or connector properties, and also 419 * adjust it according to limitations or connector properties, and also
420 * a chance to reject the mode entirely. 420 * a chance to reject the mode entirely.
421 */ 421 */
422 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 422 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
423 423
424 if (encoder->crtc != crtc) 424 if (encoder->crtc != crtc)
425 continue; 425 continue;
426 encoder_funcs = encoder->helper_private; 426 encoder_funcs = encoder->helper_private;
427 if (!(ret = encoder_funcs->mode_fixup(encoder, mode, 427 if (!(ret = encoder_funcs->mode_fixup(encoder, mode,
428 adjusted_mode))) { 428 adjusted_mode))) {
429 DRM_DEBUG_KMS("Encoder fixup failed\n"); 429 DRM_DEBUG_KMS("Encoder fixup failed\n");
430 goto done; 430 goto done;
431 } 431 }
432 } 432 }
433 433
434 if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { 434 if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
435 DRM_DEBUG_KMS("CRTC fixup failed\n"); 435 DRM_DEBUG_KMS("CRTC fixup failed\n");
436 goto done; 436 goto done;
437 } 437 }
438 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); 438 DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
439 439
440 /* Prepare the encoders and CRTCs before setting the mode. */ 440 /* Prepare the encoders and CRTCs before setting the mode. */
441 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 441 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
442 442
443 if (encoder->crtc != crtc) 443 if (encoder->crtc != crtc)
444 continue; 444 continue;
445 encoder_funcs = encoder->helper_private; 445 encoder_funcs = encoder->helper_private;
446 /* Disable the encoders as the first thing we do. */ 446 /* Disable the encoders as the first thing we do. */
447 encoder_funcs->prepare(encoder); 447 encoder_funcs->prepare(encoder);
448 } 448 }
449 449
450 drm_crtc_prepare_encoders(dev); 450 drm_crtc_prepare_encoders(dev);
451 451
452 crtc_funcs->prepare(crtc); 452 crtc_funcs->prepare(crtc);
453 453
454 /* Set up the DPLL and any encoders state that needs to adjust or depend 454 /* Set up the DPLL and any encoders state that needs to adjust or depend
455 * on the DPLL. 455 * on the DPLL.
456 */ 456 */
457 ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb); 457 ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
458 if (!ret) 458 if (!ret)
459 goto done; 459 goto done;
460 460
461 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 461 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
462 462
463 if (encoder->crtc != crtc) 463 if (encoder->crtc != crtc)
464 continue; 464 continue;
465 465
466 DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", 466 DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
467 encoder->base.id, drm_get_encoder_name(encoder), 467 encoder->base.id, drm_get_encoder_name(encoder),
468 mode->base.id, mode->name); 468 mode->base.id, mode->name);
469 encoder_funcs = encoder->helper_private; 469 encoder_funcs = encoder->helper_private;
470 encoder_funcs->mode_set(encoder, mode, adjusted_mode); 470 encoder_funcs->mode_set(encoder, mode, adjusted_mode);
471 } 471 }
472 472
473 /* Now enable the clocks, plane, pipe, and connectors that we set up. */ 473 /* Now enable the clocks, plane, pipe, and connectors that we set up. */
474 crtc_funcs->commit(crtc); 474 crtc_funcs->commit(crtc);
475 475
476 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 476 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
477 477
478 if (encoder->crtc != crtc) 478 if (encoder->crtc != crtc)
479 continue; 479 continue;
480 480
481 encoder_funcs = encoder->helper_private; 481 encoder_funcs = encoder->helper_private;
482 encoder_funcs->commit(encoder); 482 encoder_funcs->commit(encoder);
483 483
484 } 484 }
485 485
486 /* Store real post-adjustment hardware mode. */ 486 /* Store real post-adjustment hardware mode. */
487 crtc->hwmode = *adjusted_mode; 487 crtc->hwmode = *adjusted_mode;
488 488
489 /* Calculate and store various constants which 489 /* Calculate and store various constants which
490 * are later needed by vblank and swap-completion 490 * are later needed by vblank and swap-completion
491 * timestamping. They are derived from true hwmode. 491 * timestamping. They are derived from true hwmode.
492 */ 492 */
493 drm_calc_timestamping_constants(crtc); 493 drm_calc_timestamping_constants(crtc);
494 494
495 /* FIXME: add subpixel order */ 495 /* FIXME: add subpixel order */
496 done: 496 done:
497 drm_mode_destroy(dev, adjusted_mode); 497 drm_mode_destroy(dev, adjusted_mode);
498 if (!ret) { 498 if (!ret) {
499 crtc->hwmode = saved_hwmode; 499 crtc->hwmode = saved_hwmode;
500 crtc->mode = saved_mode; 500 crtc->mode = saved_mode;
501 crtc->x = saved_x; 501 crtc->x = saved_x;
502 crtc->y = saved_y; 502 crtc->y = saved_y;
503 } 503 }
504 504
505 return ret; 505 return ret;
506 } 506 }
507 EXPORT_SYMBOL(drm_crtc_helper_set_mode); 507 EXPORT_SYMBOL(drm_crtc_helper_set_mode);
508 508
509 509
510 static int 510 static int
511 drm_crtc_helper_disable(struct drm_crtc *crtc) 511 drm_crtc_helper_disable(struct drm_crtc *crtc)
512 { 512 {
513 struct drm_device *dev = crtc->dev; 513 struct drm_device *dev = crtc->dev;
514 struct drm_connector *connector; 514 struct drm_connector *connector;
515 struct drm_encoder *encoder; 515 struct drm_encoder *encoder;
516 516
517 /* Decouple all encoders and their attached connectors from this crtc */ 517 /* Decouple all encoders and their attached connectors from this crtc */
518 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 518 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
519 if (encoder->crtc != crtc) 519 if (encoder->crtc != crtc)
520 continue; 520 continue;
521 521
522 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 522 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
523 if (connector->encoder != encoder) 523 if (connector->encoder != encoder)
524 continue; 524 continue;
525 525
526 connector->encoder = NULL; 526 connector->encoder = NULL;
527 } 527 }
528 } 528 }
529 529
530 drm_helper_disable_unused_functions(dev); 530 drm_helper_disable_unused_functions(dev);
531 return 0; 531 return 0;
532 } 532 }
533 533
534 /** 534 /**
535 * drm_crtc_helper_set_config - set a new config from userspace 535 * drm_crtc_helper_set_config - set a new config from userspace
536 * @set: mode set configuration 536 * @set: mode set configuration
537 * 537 *
538 * LOCKING: 538 * LOCKING:
539 * Caller must hold mode config lock. 539 * Caller must hold mode config lock.
540 * 540 *
541 * Setup a new configuration, provided by the upper layers (either an ioctl call 541 * Setup a new configuration, provided by the upper layers (either an ioctl call
542 * from userspace or internally e.g. from the fbdev suppport code) in @set, and 542 * from userspace or internally e.g. from the fbdev suppport code) in @set, and
543 * enable it. This is the main helper functions for drivers that implement 543 * enable it. This is the main helper functions for drivers that implement
544 * kernel mode setting with the crtc helper functions and the assorted 544 * kernel mode setting with the crtc helper functions and the assorted
545 * ->prepare(), ->modeset() and ->commit() helper callbacks. 545 * ->prepare(), ->modeset() and ->commit() helper callbacks.
546 * 546 *
547 * RETURNS: 547 * RETURNS:
548 * Returns 0 on success, -ERRNO on failure. 548 * Returns 0 on success, -ERRNO on failure.
549 */ 549 */
550 int drm_crtc_helper_set_config(struct drm_mode_set *set) 550 int drm_crtc_helper_set_config(struct drm_mode_set *set)
551 { 551 {
552 struct drm_device *dev; 552 struct drm_device *dev;
553 struct drm_crtc *save_crtcs, *new_crtc, *crtc; 553 struct drm_crtc *save_crtcs, *new_crtc, *crtc;
554 struct drm_encoder *save_encoders, *new_encoder, *encoder; 554 struct drm_encoder *save_encoders, *new_encoder, *encoder;
555 struct drm_framebuffer *old_fb = NULL; 555 struct drm_framebuffer *old_fb = NULL;
556 bool mode_changed = false; /* if true do a full mode set */ 556 bool mode_changed = false; /* if true do a full mode set */
557 bool fb_changed = false; /* if true and !mode_changed just do a flip */ 557 bool fb_changed = false; /* if true and !mode_changed just do a flip */
558 struct drm_connector *save_connectors, *connector; 558 struct drm_connector *save_connectors, *connector;
559 int count = 0, ro, fail = 0; 559 int count = 0, ro, fail = 0;
560 struct drm_crtc_helper_funcs *crtc_funcs; 560 struct drm_crtc_helper_funcs *crtc_funcs;
561 struct drm_mode_set save_set; 561 struct drm_mode_set save_set;
562 int ret; 562 int ret;
563 int i; 563 int i;
564 564
565 DRM_DEBUG_KMS("\n"); 565 DRM_DEBUG_KMS("\n");
566 566
567 if (!set) 567 if (!set)
568 return -EINVAL; 568 return -EINVAL;
569 569
570 if (!set->crtc) 570 if (!set->crtc)
571 return -EINVAL; 571 return -EINVAL;
572 572
573 if (!set->crtc->helper_private) 573 if (!set->crtc->helper_private)
574 return -EINVAL; 574 return -EINVAL;
575 575
576 crtc_funcs = set->crtc->helper_private; 576 crtc_funcs = set->crtc->helper_private;
577 577
578 if (!set->mode) 578 if (!set->mode)
579 set->fb = NULL; 579 set->fb = NULL;
580 580
581 if (set->fb) { 581 if (set->fb) {
582 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", 582 DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
583 set->crtc->base.id, set->fb->base.id, 583 set->crtc->base.id, set->fb->base.id,
584 (int)set->num_connectors, set->x, set->y); 584 (int)set->num_connectors, set->x, set->y);
585 } else { 585 } else {
586 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); 586 DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id);
587 return drm_crtc_helper_disable(set->crtc); 587 return drm_crtc_helper_disable(set->crtc);
588 } 588 }
589 589
590 dev = set->crtc->dev; 590 dev = set->crtc->dev;
591 591
592 /* Allocate space for the backup of all (non-pointer) crtc, encoder and 592 /* Allocate space for the backup of all (non-pointer) crtc, encoder and
593 * connector data. */ 593 * connector data. */
594 save_crtcs = kzalloc(dev->mode_config.num_crtc * 594 save_crtcs = kzalloc(dev->mode_config.num_crtc *
595 sizeof(struct drm_crtc), GFP_KERNEL); 595 sizeof(struct drm_crtc), GFP_KERNEL);
596 if (!save_crtcs) 596 if (!save_crtcs)
597 return -ENOMEM; 597 return -ENOMEM;
598 598
599 save_encoders = kzalloc(dev->mode_config.num_encoder * 599 save_encoders = kzalloc(dev->mode_config.num_encoder *
600 sizeof(struct drm_encoder), GFP_KERNEL); 600 sizeof(struct drm_encoder), GFP_KERNEL);
601 if (!save_encoders) { 601 if (!save_encoders) {
602 kfree(save_crtcs); 602 kfree(save_crtcs);
603 return -ENOMEM; 603 return -ENOMEM;
604 } 604 }
605 605
606 save_connectors = kzalloc(dev->mode_config.num_connector * 606 save_connectors = kzalloc(dev->mode_config.num_connector *
607 sizeof(struct drm_connector), GFP_KERNEL); 607 sizeof(struct drm_connector), GFP_KERNEL);
608 if (!save_connectors) { 608 if (!save_connectors) {
609 kfree(save_crtcs); 609 kfree(save_crtcs);
610 kfree(save_encoders); 610 kfree(save_encoders);
611 return -ENOMEM; 611 return -ENOMEM;
612 } 612 }
613 613
614 /* Copy data. Note that driver private data is not affected. 614 /* Copy data. Note that driver private data is not affected.
615 * Should anything bad happen only the expected state is 615 * Should anything bad happen only the expected state is
616 * restored, not the drivers personal bookkeeping. 616 * restored, not the drivers personal bookkeeping.
617 */ 617 */
618 count = 0; 618 count = 0;
619 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 619 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
620 save_crtcs[count++] = *crtc; 620 save_crtcs[count++] = *crtc;
621 } 621 }
622 622
623 count = 0; 623 count = 0;
624 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 624 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
625 save_encoders[count++] = *encoder; 625 save_encoders[count++] = *encoder;
626 } 626 }
627 627
628 count = 0; 628 count = 0;
629 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 629 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
630 save_connectors[count++] = *connector; 630 save_connectors[count++] = *connector;
631 } 631 }
632 632
633 save_set.crtc = set->crtc; 633 save_set.crtc = set->crtc;
634 save_set.mode = &set->crtc->mode; 634 save_set.mode = &set->crtc->mode;
635 save_set.x = set->crtc->x; 635 save_set.x = set->crtc->x;
636 save_set.y = set->crtc->y; 636 save_set.y = set->crtc->y;
637 save_set.fb = set->crtc->fb; 637 save_set.fb = set->crtc->fb;
638 638
639 /* We should be able to check here if the fb has the same properties 639 /* We should be able to check here if the fb has the same properties
640 * and then just flip_or_move it */ 640 * and then just flip_or_move it */
641 if (set->crtc->fb != set->fb) { 641 if (set->crtc->fb != set->fb) {
642 /* If we have no fb then treat it as a full mode set */ 642 /* If we have no fb then treat it as a full mode set */
643 if (set->crtc->fb == NULL) { 643 if (set->crtc->fb == NULL) {
644 DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); 644 DRM_DEBUG_KMS("crtc has no fb, full mode set\n");
645 mode_changed = true; 645 mode_changed = true;
646 } else if (set->fb == NULL) { 646 } else if (set->fb == NULL) {
647 mode_changed = true; 647 mode_changed = true;
648 } else if (set->fb->depth != set->crtc->fb->depth) { 648 } else if (set->fb->depth != set->crtc->fb->depth) {
649 mode_changed = true; 649 mode_changed = true;
650 } else if (set->fb->bits_per_pixel != 650 } else if (set->fb->bits_per_pixel !=
651 set->crtc->fb->bits_per_pixel) { 651 set->crtc->fb->bits_per_pixel) {
652 mode_changed = true; 652 mode_changed = true;
653 } else if (set->fb->pixel_format != 653 } else if (set->fb->pixel_format !=
654 set->crtc->fb->pixel_format) { 654 set->crtc->fb->pixel_format) {
655 mode_changed = true; 655 mode_changed = true;
656 } else 656 } else
657 fb_changed = true; 657 fb_changed = true;
658 } 658 }
659 659
660 if (set->x != set->crtc->x || set->y != set->crtc->y) 660 if (set->x != set->crtc->x || set->y != set->crtc->y)
661 fb_changed = true; 661 fb_changed = true;
662 662
663 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { 663 if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) {
664 DRM_DEBUG_KMS("modes are different, full mode set\n"); 664 DRM_DEBUG_KMS("modes are different, full mode set\n");
665 drm_mode_debug_printmodeline(&set->crtc->mode); 665 drm_mode_debug_printmodeline(&set->crtc->mode);
666 drm_mode_debug_printmodeline(set->mode); 666 drm_mode_debug_printmodeline(set->mode);
667 mode_changed = true; 667 mode_changed = true;
668 } 668 }
669 669
670 /* a) traverse passed in connector list and get encoders for them */ 670 /* a) traverse passed in connector list and get encoders for them */
671 count = 0; 671 count = 0;
672 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 672 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
673 struct drm_connector_helper_funcs *connector_funcs = 673 struct drm_connector_helper_funcs *connector_funcs =
674 connector->helper_private; 674 connector->helper_private;
675 new_encoder = connector->encoder; 675 new_encoder = connector->encoder;
676 for (ro = 0; ro < set->num_connectors; ro++) { 676 for (ro = 0; ro < set->num_connectors; ro++) {
677 if (set->connectors[ro] == connector) { 677 if (set->connectors[ro] == connector) {
678 new_encoder = connector_funcs->best_encoder(connector); 678 new_encoder = connector_funcs->best_encoder(connector);
679 /* if we can't get an encoder for a connector 679 /* if we can't get an encoder for a connector
680 we are setting now - then fail */ 680 we are setting now - then fail */
681 if (new_encoder == NULL) 681 if (new_encoder == NULL)
682 /* don't break so fail path works correct */ 682 /* don't break so fail path works correct */
683 fail = 1; 683 fail = 1;
684 break; 684 break;
685 } 685 }
686 } 686 }
687 687
688 if (new_encoder != connector->encoder) { 688 if (new_encoder != connector->encoder) {
689 DRM_DEBUG_KMS("encoder changed, full mode switch\n"); 689 DRM_DEBUG_KMS("encoder changed, full mode switch\n");
690 mode_changed = true; 690 mode_changed = true;
691 /* If the encoder is reused for another connector, then 691 /* If the encoder is reused for another connector, then
692 * the appropriate crtc will be set later. 692 * the appropriate crtc will be set later.
693 */ 693 */
694 if (connector->encoder) 694 if (connector->encoder)
695 connector->encoder->crtc = NULL; 695 connector->encoder->crtc = NULL;
696 connector->encoder = new_encoder; 696 connector->encoder = new_encoder;
697 } 697 }
698 } 698 }
699 699
700 if (fail) { 700 if (fail) {
701 ret = -EINVAL; 701 ret = -EINVAL;
702 goto fail; 702 goto fail;
703 } 703 }
704 704
705 count = 0; 705 count = 0;
706 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 706 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
707 if (!connector->encoder) 707 if (!connector->encoder)
708 continue; 708 continue;
709 709
710 if (connector->encoder->crtc == set->crtc) 710 if (connector->encoder->crtc == set->crtc)
711 new_crtc = NULL; 711 new_crtc = NULL;
712 else 712 else
713 new_crtc = connector->encoder->crtc; 713 new_crtc = connector->encoder->crtc;
714 714
715 for (ro = 0; ro < set->num_connectors; ro++) { 715 for (ro = 0; ro < set->num_connectors; ro++) {
716 if (set->connectors[ro] == connector) 716 if (set->connectors[ro] == connector)
717 new_crtc = set->crtc; 717 new_crtc = set->crtc;
718 } 718 }
719 719
720 /* Make sure the new CRTC will work with the encoder */ 720 /* Make sure the new CRTC will work with the encoder */
721 if (new_crtc && 721 if (new_crtc &&
722 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { 722 !drm_encoder_crtc_ok(connector->encoder, new_crtc)) {
723 ret = -EINVAL; 723 ret = -EINVAL;
724 goto fail; 724 goto fail;
725 } 725 }
726 if (new_crtc != connector->encoder->crtc) { 726 if (new_crtc != connector->encoder->crtc) {
727 DRM_DEBUG_KMS("crtc changed, full mode switch\n"); 727 DRM_DEBUG_KMS("crtc changed, full mode switch\n");
728 mode_changed = true; 728 mode_changed = true;
729 connector->encoder->crtc = new_crtc; 729 connector->encoder->crtc = new_crtc;
730 } 730 }
731 if (new_crtc) { 731 if (new_crtc) {
732 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", 732 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
733 connector->base.id, drm_get_connector_name(connector), 733 connector->base.id, drm_get_connector_name(connector),
734 new_crtc->base.id); 734 new_crtc->base.id);
735 } else { 735 } else {
736 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", 736 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
737 connector->base.id, drm_get_connector_name(connector)); 737 connector->base.id, drm_get_connector_name(connector));
738 } 738 }
739 } 739 }
740 740
741 /* mode_set_base is not a required function */ 741 /* mode_set_base is not a required function */
742 if (fb_changed && !crtc_funcs->mode_set_base) 742 if (fb_changed && !crtc_funcs->mode_set_base)
743 mode_changed = true; 743 mode_changed = true;
744 744
745 if (mode_changed) { 745 if (mode_changed) {
746 set->crtc->enabled = drm_helper_crtc_in_use(set->crtc); 746 set->crtc->enabled = drm_helper_crtc_in_use(set->crtc);
747 if (set->crtc->enabled) { 747 if (set->crtc->enabled) {
748 DRM_DEBUG_KMS("attempting to set mode from" 748 DRM_DEBUG_KMS("attempting to set mode from"
749 " userspace\n"); 749 " userspace\n");
750 drm_mode_debug_printmodeline(set->mode); 750 drm_mode_debug_printmodeline(set->mode);
751 old_fb = set->crtc->fb; 751 old_fb = set->crtc->fb;
752 set->crtc->fb = set->fb; 752 set->crtc->fb = set->fb;
753 if (!drm_crtc_helper_set_mode(set->crtc, set->mode, 753 if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
754 set->x, set->y, 754 set->x, set->y,
755 old_fb)) { 755 old_fb)) {
756 DRM_ERROR("failed to set mode on [CRTC:%d]\n", 756 DRM_ERROR("failed to set mode on [CRTC:%d]\n",
757 set->crtc->base.id); 757 set->crtc->base.id);
758 set->crtc->fb = old_fb; 758 set->crtc->fb = old_fb;
759 ret = -EINVAL; 759 ret = -EINVAL;
760 goto fail; 760 goto fail;
761 } 761 }
762 DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); 762 DRM_DEBUG_KMS("Setting connector DPMS state to on\n");
763 for (i = 0; i < set->num_connectors; i++) { 763 for (i = 0; i < set->num_connectors; i++) {
764 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, 764 DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id,
765 drm_get_connector_name(set->connectors[i])); 765 drm_get_connector_name(set->connectors[i]));
766 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); 766 set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON);
767 } 767 }
768 } 768 }
769 drm_helper_disable_unused_functions(dev); 769 drm_helper_disable_unused_functions(dev);
770 } else if (fb_changed) { 770 } else if (fb_changed) {
771 set->crtc->x = set->x; 771 set->crtc->x = set->x;
772 set->crtc->y = set->y; 772 set->crtc->y = set->y;
773 773
774 old_fb = set->crtc->fb; 774 old_fb = set->crtc->fb;
775 if (set->crtc->fb != set->fb) 775 if (set->crtc->fb != set->fb)
776 set->crtc->fb = set->fb; 776 set->crtc->fb = set->fb;
777 ret = crtc_funcs->mode_set_base(set->crtc, 777 ret = crtc_funcs->mode_set_base(set->crtc,
778 set->x, set->y, old_fb); 778 set->x, set->y, old_fb);
779 if (ret != 0) { 779 if (ret != 0) {
780 set->crtc->fb = old_fb; 780 set->crtc->fb = old_fb;
781 goto fail; 781 goto fail;
782 } 782 }
783 } 783 }
784 784
785 kfree(save_connectors); 785 kfree(save_connectors);
786 kfree(save_encoders); 786 kfree(save_encoders);
787 kfree(save_crtcs); 787 kfree(save_crtcs);
788 return 0; 788 return 0;
789 789
790 fail: 790 fail:
791 /* Restore all previous data. */ 791 /* Restore all previous data. */
792 count = 0; 792 count = 0;
793 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 793 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
794 *crtc = save_crtcs[count++]; 794 *crtc = save_crtcs[count++];
795 } 795 }
796 796
797 count = 0; 797 count = 0;
798 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 798 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
799 *encoder = save_encoders[count++]; 799 *encoder = save_encoders[count++];
800 } 800 }
801 801
802 count = 0; 802 count = 0;
803 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 803 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
804 *connector = save_connectors[count++]; 804 *connector = save_connectors[count++];
805 } 805 }
806 806
807 /* Try to restore the config */ 807 /* Try to restore the config */
808 if (mode_changed && 808 if (mode_changed &&
809 !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x, 809 !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
810 save_set.y, save_set.fb)) 810 save_set.y, save_set.fb))
811 DRM_ERROR("failed to restore config after modeset failure\n"); 811 DRM_ERROR("failed to restore config after modeset failure\n");
812 812
813 kfree(save_connectors); 813 kfree(save_connectors);
814 kfree(save_encoders); 814 kfree(save_encoders);
815 kfree(save_crtcs); 815 kfree(save_crtcs);
816 return ret; 816 return ret;
817 } 817 }
818 EXPORT_SYMBOL(drm_crtc_helper_set_config); 818 EXPORT_SYMBOL(drm_crtc_helper_set_config);
819 819
820 static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) 820 static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
821 { 821 {
822 int dpms = DRM_MODE_DPMS_OFF; 822 int dpms = DRM_MODE_DPMS_OFF;
823 struct drm_connector *connector; 823 struct drm_connector *connector;
824 struct drm_device *dev = encoder->dev; 824 struct drm_device *dev = encoder->dev;
825 825
826 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 826 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
827 if (connector->encoder == encoder) 827 if (connector->encoder == encoder)
828 if (connector->dpms < dpms) 828 if (connector->dpms < dpms)
829 dpms = connector->dpms; 829 dpms = connector->dpms;
830 return dpms; 830 return dpms;
831 } 831 }
832 832
833 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) 833 static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
834 { 834 {
835 int dpms = DRM_MODE_DPMS_OFF; 835 int dpms = DRM_MODE_DPMS_OFF;
836 struct drm_connector *connector; 836 struct drm_connector *connector;
837 struct drm_device *dev = crtc->dev; 837 struct drm_device *dev = crtc->dev;
838 838
839 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 839 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
840 if (connector->encoder && connector->encoder->crtc == crtc) 840 if (connector->encoder && connector->encoder->crtc == crtc)
841 if (connector->dpms < dpms) 841 if (connector->dpms < dpms)
842 dpms = connector->dpms; 842 dpms = connector->dpms;
843 return dpms; 843 return dpms;
844 } 844 }
845 845
846 /** 846 /**
847 * drm_helper_connector_dpms() - connector dpms helper implementation 847 * drm_helper_connector_dpms() - connector dpms helper implementation
848 * @connector: affected connector 848 * @connector: affected connector
849 * @mode: DPMS mode 849 * @mode: DPMS mode
850 * 850 *
851 * This is the main helper function provided by the crtc helper framework for 851 * This is the main helper function provided by the crtc helper framework for
852 * implementing the DPMS connector attribute. It computes the new desired DPMS 852 * implementing the DPMS connector attribute. It computes the new desired DPMS
853 * state for all encoders and crtcs in the output mesh and calls the ->dpms() 853 * state for all encoders and crtcs in the output mesh and calls the ->dpms()
854 * callback provided by the driver appropriately. 854 * callback provided by the driver appropriately.
855 */ 855 */
856 void drm_helper_connector_dpms(struct drm_connector *connector, int mode) 856 void drm_helper_connector_dpms(struct drm_connector *connector, int mode)
857 { 857 {
858 struct drm_encoder *encoder = connector->encoder; 858 struct drm_encoder *encoder = connector->encoder;
859 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; 859 struct drm_crtc *crtc = encoder ? encoder->crtc : NULL;
860 int old_dpms; 860 int old_dpms;
861 861
862 if (mode == connector->dpms) 862 if (mode == connector->dpms)
863 return; 863 return;
864 864
865 old_dpms = connector->dpms; 865 old_dpms = connector->dpms;
866 connector->dpms = mode; 866 connector->dpms = mode;
867 867
868 /* from off to on, do crtc then encoder */ 868 /* from off to on, do crtc then encoder */
869 if (mode < old_dpms) { 869 if (mode < old_dpms) {
870 if (crtc) { 870 if (crtc) {
871 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 871 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
872 if (crtc_funcs->dpms) 872 if (crtc_funcs->dpms)
873 (*crtc_funcs->dpms) (crtc, 873 (*crtc_funcs->dpms) (crtc,
874 drm_helper_choose_crtc_dpms(crtc)); 874 drm_helper_choose_crtc_dpms(crtc));
875 } 875 }
876 if (encoder) { 876 if (encoder) {
877 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 877 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
878 if (encoder_funcs->dpms) 878 if (encoder_funcs->dpms)
879 (*encoder_funcs->dpms) (encoder, 879 (*encoder_funcs->dpms) (encoder,
880 drm_helper_choose_encoder_dpms(encoder)); 880 drm_helper_choose_encoder_dpms(encoder));
881 } 881 }
882 } 882 }
883 883
884 /* from on to off, do encoder then crtc */ 884 /* from on to off, do encoder then crtc */
885 if (mode > old_dpms) { 885 if (mode > old_dpms) {
886 if (encoder) { 886 if (encoder) {
887 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; 887 struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
888 if (encoder_funcs->dpms) 888 if (encoder_funcs->dpms)
889 (*encoder_funcs->dpms) (encoder, 889 (*encoder_funcs->dpms) (encoder,
890 drm_helper_choose_encoder_dpms(encoder)); 890 drm_helper_choose_encoder_dpms(encoder));
891 } 891 }
892 if (crtc) { 892 if (crtc) {
893 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 893 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
894 if (crtc_funcs->dpms) 894 if (crtc_funcs->dpms)
895 (*crtc_funcs->dpms) (crtc, 895 (*crtc_funcs->dpms) (crtc,
896 drm_helper_choose_crtc_dpms(crtc)); 896 drm_helper_choose_crtc_dpms(crtc));
897 } 897 }
898 } 898 }
899 899
900 return; 900 return;
901 } 901 }
902 EXPORT_SYMBOL(drm_helper_connector_dpms); 902 EXPORT_SYMBOL(drm_helper_connector_dpms);
903 903
904 int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, 904 int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
905 struct drm_mode_fb_cmd2 *mode_cmd) 905 struct drm_mode_fb_cmd2 *mode_cmd)
906 { 906 {
907 int i; 907 int i;
908 908
909 fb->width = mode_cmd->width; 909 fb->width = mode_cmd->width;
910 fb->height = mode_cmd->height; 910 fb->height = mode_cmd->height;
911 for (i = 0; i < 4; i++) { 911 for (i = 0; i < 4; i++) {
912 fb->pitches[i] = mode_cmd->pitches[i]; 912 fb->pitches[i] = mode_cmd->pitches[i];
913 fb->offsets[i] = mode_cmd->offsets[i]; 913 fb->offsets[i] = mode_cmd->offsets[i];
914 } 914 }
915 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, 915 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
916 &fb->bits_per_pixel); 916 &fb->bits_per_pixel);
917 fb->pixel_format = mode_cmd->pixel_format; 917 fb->pixel_format = mode_cmd->pixel_format;
918 918
919 return 0; 919 return 0;
920 } 920 }
921 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); 921 EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
922 922
923 int drm_helper_resume_force_mode(struct drm_device *dev) 923 int drm_helper_resume_force_mode(struct drm_device *dev)
924 { 924 {
925 struct drm_crtc *crtc; 925 struct drm_crtc *crtc;
926 struct drm_encoder *encoder; 926 struct drm_encoder *encoder;
927 struct drm_encoder_helper_funcs *encoder_funcs; 927 struct drm_encoder_helper_funcs *encoder_funcs;
928 struct drm_crtc_helper_funcs *crtc_funcs; 928 struct drm_crtc_helper_funcs *crtc_funcs;
929 int ret; 929 int ret;
930 930
931 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 931 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
932 932
933 if (!crtc->enabled) 933 if (!crtc->enabled)
934 continue; 934 continue;
935 935
936 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, 936 ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
937 crtc->x, crtc->y, crtc->fb); 937 crtc->x, crtc->y, crtc->fb);
938 938
939 if (ret == false) 939 if (ret == false)
940 DRM_ERROR("failed to set mode on crtc %p\n", crtc); 940 DRM_ERROR("failed to set mode on crtc %p\n", crtc);
941 941
942 /* Turn off outputs that were already powered off */ 942 /* Turn off outputs that were already powered off */
943 if (drm_helper_choose_crtc_dpms(crtc)) { 943 if (drm_helper_choose_crtc_dpms(crtc)) {
944 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 944 list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
945 945
946 if(encoder->crtc != crtc) 946 if(encoder->crtc != crtc)
947 continue; 947 continue;
948 948
949 encoder_funcs = encoder->helper_private; 949 encoder_funcs = encoder->helper_private;
950 if (encoder_funcs->dpms) 950 if (encoder_funcs->dpms)
951 (*encoder_funcs->dpms) (encoder, 951 (*encoder_funcs->dpms) (encoder,
952 drm_helper_choose_encoder_dpms(encoder)); 952 drm_helper_choose_encoder_dpms(encoder));
953 } 953 }
954 954
955 crtc_funcs = crtc->helper_private; 955 crtc_funcs = crtc->helper_private;
956 if (crtc_funcs->dpms) 956 if (crtc_funcs->dpms)
957 (*crtc_funcs->dpms) (crtc, 957 (*crtc_funcs->dpms) (crtc,
958 drm_helper_choose_crtc_dpms(crtc)); 958 drm_helper_choose_crtc_dpms(crtc));
959 } 959 }
960 } 960 }
961 /* disable the unused connectors while restoring the modesetting */ 961 /* disable the unused connectors while restoring the modesetting */
962 drm_helper_disable_unused_functions(dev); 962 drm_helper_disable_unused_functions(dev);
963 return 0; 963 return 0;
964 } 964 }
965 EXPORT_SYMBOL(drm_helper_resume_force_mode); 965 EXPORT_SYMBOL(drm_helper_resume_force_mode);
966 966
967 void drm_kms_helper_hotplug_event(struct drm_device *dev) 967 void drm_kms_helper_hotplug_event(struct drm_device *dev)
968 { 968 {
969 /* send a uevent + call fbdev */ 969 /* send a uevent + call fbdev */
970 drm_sysfs_hotplug_event(dev); 970 drm_sysfs_hotplug_event(dev);
971 if (dev->mode_config.funcs->output_poll_changed) 971 if (dev->mode_config.funcs->output_poll_changed)
972 dev->mode_config.funcs->output_poll_changed(dev); 972 dev->mode_config.funcs->output_poll_changed(dev);
973 } 973 }
974 EXPORT_SYMBOL(drm_kms_helper_hotplug_event); 974 EXPORT_SYMBOL(drm_kms_helper_hotplug_event);
975 975
976 #define DRM_OUTPUT_POLL_PERIOD (10*HZ) 976 #define DRM_OUTPUT_POLL_PERIOD (10*HZ)
977 static void output_poll_execute(struct work_struct *work) 977 static void output_poll_execute(struct work_struct *work)
978 { 978 {
979 struct delayed_work *delayed_work = to_delayed_work(work); 979 struct delayed_work *delayed_work = to_delayed_work(work);
980 struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); 980 struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work);
981 struct drm_connector *connector; 981 struct drm_connector *connector;
982 enum drm_connector_status old_status; 982 enum drm_connector_status old_status;
983 bool repoll = false, changed = false; 983 bool repoll = false, changed = false;
984 984
985 if (!drm_kms_helper_poll) 985 if (!drm_kms_helper_poll)
986 return; 986 return;
987 987
988 mutex_lock(&dev->mode_config.mutex); 988 mutex_lock(&dev->mode_config.mutex);
989 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 989 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
990 990
991 /* Ignore forced connectors. */ 991 /* Ignore forced connectors. */
992 if (connector->force) 992 if (connector->force)
993 continue; 993 continue;
994 994
995 /* Ignore HPD capable connectors and connectors where we don't 995 /* Ignore HPD capable connectors and connectors where we don't
996 * want any hotplug detection at all for polling. */ 996 * want any hotplug detection at all for polling. */
997 if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) 997 if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD)
998 continue; 998 continue;
999 999
1000 repoll = true; 1000 repoll = true;
1001 1001
1002 old_status = connector->status; 1002 old_status = connector->status;
1003 /* if we are connected and don't want to poll for disconnect 1003 /* if we are connected and don't want to poll for disconnect
1004 skip it */ 1004 skip it */
1005 if (old_status == connector_status_connected && 1005 if (old_status == connector_status_connected &&
1006 !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) 1006 !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT))
1007 continue; 1007 continue;
1008 1008
1009 connector->status = connector->funcs->detect(connector, false); 1009 connector->status = connector->funcs->detect(connector, false);
1010 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", 1010 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
1011 connector->base.id, 1011 connector->base.id,
1012 drm_get_connector_name(connector), 1012 drm_get_connector_name(connector),
1013 old_status, connector->status); 1013 drm_get_connector_status_name(old_status),
1014 drm_get_connector_status_name(connector->status));
1014 if (old_status != connector->status) 1015 if (old_status != connector->status)
1015 changed = true; 1016 changed = true;
1016 } 1017 }
1017 1018
1018 mutex_unlock(&dev->mode_config.mutex); 1019 mutex_unlock(&dev->mode_config.mutex);
1019 1020
1020 if (changed) 1021 if (changed)
1021 drm_kms_helper_hotplug_event(dev); 1022 drm_kms_helper_hotplug_event(dev);
1022 1023
1023 if (repoll) 1024 if (repoll)
1024 schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); 1025 schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD);
1025 } 1026 }
1026 1027
1027 void drm_kms_helper_poll_disable(struct drm_device *dev) 1028 void drm_kms_helper_poll_disable(struct drm_device *dev)
1028 { 1029 {
1029 if (!dev->mode_config.poll_enabled) 1030 if (!dev->mode_config.poll_enabled)
1030 return; 1031 return;
1031 cancel_delayed_work_sync(&dev->mode_config.output_poll_work); 1032 cancel_delayed_work_sync(&dev->mode_config.output_poll_work);
1032 } 1033 }
1033 EXPORT_SYMBOL(drm_kms_helper_poll_disable); 1034 EXPORT_SYMBOL(drm_kms_helper_poll_disable);
1034 1035
1035 void drm_kms_helper_poll_enable(struct drm_device *dev) 1036 void drm_kms_helper_poll_enable(struct drm_device *dev)
1036 { 1037 {
1037 bool poll = false; 1038 bool poll = false;
1038 struct drm_connector *connector; 1039 struct drm_connector *connector;
1039 1040
1040 if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) 1041 if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
1041 return; 1042 return;
1042 1043
1043 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1044 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1044 if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | 1045 if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
1045 DRM_CONNECTOR_POLL_DISCONNECT)) 1046 DRM_CONNECTOR_POLL_DISCONNECT))
1046 poll = true; 1047 poll = true;
1047 } 1048 }
1048 1049
1049 if (poll) 1050 if (poll)
1050 schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); 1051 schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD);
1051 } 1052 }
1052 EXPORT_SYMBOL(drm_kms_helper_poll_enable); 1053 EXPORT_SYMBOL(drm_kms_helper_poll_enable);
1053 1054
1054 void drm_kms_helper_poll_init(struct drm_device *dev) 1055 void drm_kms_helper_poll_init(struct drm_device *dev)
1055 { 1056 {
1056 INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); 1057 INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute);
1057 dev->mode_config.poll_enabled = true; 1058 dev->mode_config.poll_enabled = true;
1058 1059
1059 drm_kms_helper_poll_enable(dev); 1060 drm_kms_helper_poll_enable(dev);
1060 } 1061 }
1061 EXPORT_SYMBOL(drm_kms_helper_poll_init); 1062 EXPORT_SYMBOL(drm_kms_helper_poll_init);
1062 1063
1063 void drm_kms_helper_poll_fini(struct drm_device *dev) 1064 void drm_kms_helper_poll_fini(struct drm_device *dev)
1064 { 1065 {
1065 drm_kms_helper_poll_disable(dev); 1066 drm_kms_helper_poll_disable(dev);
1066 } 1067 }
1067 EXPORT_SYMBOL(drm_kms_helper_poll_fini); 1068 EXPORT_SYMBOL(drm_kms_helper_poll_fini);
1068 1069
1069 void drm_helper_hpd_irq_event(struct drm_device *dev) 1070 void drm_helper_hpd_irq_event(struct drm_device *dev)
1070 { 1071 {
1071 struct drm_connector *connector; 1072 struct drm_connector *connector;
1072 enum drm_connector_status old_status; 1073 enum drm_connector_status old_status;
1073 bool changed = false; 1074 bool changed = false;
1074 1075
1075 if (!dev->mode_config.poll_enabled) 1076 if (!dev->mode_config.poll_enabled)
1076 return; 1077 return;
1077 1078
1078 mutex_lock(&dev->mode_config.mutex); 1079 mutex_lock(&dev->mode_config.mutex);
1079 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 1080 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
1080 1081
1081 /* Only handle HPD capable connectors. */ 1082 /* Only handle HPD capable connectors. */
1082 if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) 1083 if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
1083 continue; 1084 continue;
1084 1085
1085 old_status = connector->status; 1086 old_status = connector->status;
1086 1087
1087 connector->status = connector->funcs->detect(connector, false); 1088 connector->status = connector->funcs->detect(connector, false);
1088 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n", 1089 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n",
1089 connector->base.id, 1090 connector->base.id,
1090 drm_get_connector_name(connector), 1091 drm_get_connector_name(connector),
1091 old_status, connector->status); 1092 drm_get_connector_status_name(old_status),
1093 drm_get_connector_status_name(connector->status));
1092 if (old_status != connector->status) 1094 if (old_status != connector->status)
1093 changed = true; 1095 changed = true;
1094 } 1096 }
1095 1097
1096 mutex_unlock(&dev->mode_config.mutex); 1098 mutex_unlock(&dev->mode_config.mutex);
1097 1099
1098 if (changed) 1100 if (changed)
1099 drm_kms_helper_hotplug_event(dev); 1101 drm_kms_helper_hotplug_event(dev);
1100 } 1102 }
1101 EXPORT_SYMBOL(drm_helper_hpd_irq_event); 1103 EXPORT_SYMBOL(drm_helper_hpd_irq_event);
1102 1104