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