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