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