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