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