]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/drm2/drm_crtc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / drm2 / 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 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <dev/drm2/drm.h>
36 #include <dev/drm2/drmP.h>
37 #include <dev/drm2/drm_crtc.h>
38 #include <dev/drm2/drm_edid.h>
39 #include <dev/drm2/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         snprintf(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         snprintf(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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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                 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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
565         drm_mode_object_put(dev, &encoder->base);
566         list_del(&encoder->head);
567         dev->mode_config.num_encoder--;
568         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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 = malloc(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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
616         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         sx_xunlock(&dev->mode_config.mutex);
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 = malloc(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                 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         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         sx_init(&dev->mode_config.mutex, "kmslk");
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         sx_xlock(&dev->mode_config.mutex);
897         drm_mode_create_standard_connector_properties(dev);
898         sx_xunlock(&dev->mode_config.mutex);
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 = malloc(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                 printf("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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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 = malloc(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         free(connector_set, DRM_MEM_KMS);
1941         drm_mode_destroy(dev, mode);
1942         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         sx_xunlock(&dev->mode_config.mutex);
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         sx_xlock(&dev->mode_config.mutex);
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         r->handle = 0;
2321         fb->funcs->create_handle(fb, file_priv, &r->handle);
2322
2323 out:
2324         sx_xunlock(&dev->mode_config.mutex);
2325         return ret;
2326 }
2327
2328 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2329                            void *data, struct drm_file *file_priv)
2330 {
2331         struct drm_clip_rect __user *clips_ptr;
2332         struct drm_clip_rect *clips = NULL;
2333         struct drm_mode_fb_dirty_cmd *r = data;
2334         struct drm_mode_object *obj;
2335         struct drm_framebuffer *fb;
2336         unsigned flags;
2337         int num_clips;
2338         int ret = 0;
2339
2340         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2341                 return (EINVAL);
2342
2343         sx_xlock(&dev->mode_config.mutex);
2344         obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2345         if (!obj) {
2346                 ret = EINVAL;
2347                 goto out_err1;
2348         }
2349         fb = obj_to_fb(obj);
2350
2351         num_clips = r->num_clips;
2352         clips_ptr = (struct drm_clip_rect *)(unsigned long)r->clips_ptr;
2353
2354         if (!num_clips != !clips_ptr) {
2355                 ret = EINVAL;
2356                 goto out_err1;
2357         }
2358
2359         flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
2360
2361         /* If userspace annotates copy, clips must come in pairs */
2362         if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
2363                 ret = EINVAL;
2364                 goto out_err1;
2365         }
2366
2367         if (num_clips && clips_ptr) {
2368                 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
2369                         ret = EINVAL;
2370                         goto out_err1;
2371                 }
2372                 clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
2373                     M_WAITOK | M_ZERO);
2374
2375                 ret = copyin(clips_ptr, clips, num_clips * sizeof(*clips));
2376                 if (ret)
2377                         goto out_err2;
2378         }
2379
2380         if (fb->funcs->dirty) {
2381                 ret = -fb->funcs->dirty(fb, file_priv, flags, r->color,
2382                                        clips, num_clips);
2383         } else {
2384                 ret = ENOSYS;
2385                 goto out_err2;
2386         }
2387
2388 out_err2:
2389         free(clips, DRM_MEM_KMS);
2390 out_err1:
2391         sx_xunlock(&dev->mode_config.mutex);
2392         return ret;
2393 }
2394
2395
2396 /**
2397  * drm_fb_release - remove and free the FBs on this file
2398  * @filp: file * from the ioctl
2399  *
2400  * LOCKING:
2401  * Takes mode config lock.
2402  *
2403  * Destroy all the FBs associated with @filp.
2404  *
2405  * Called by the user via ioctl.
2406  *
2407  * RETURNS:
2408  * Zero on success, errno on failure.
2409  */
2410 void drm_fb_release(struct drm_file *priv)
2411 {
2412 #if 1
2413         struct drm_device *dev = priv->dev;
2414 #else
2415         struct drm_device *dev = priv->minor->dev;
2416 #endif
2417         struct drm_framebuffer *fb, *tfb;
2418
2419         sx_xlock(&dev->mode_config.mutex);
2420         list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2421                 list_del(&fb->filp_head);
2422                 fb->funcs->destroy(fb);
2423         }
2424         sx_xunlock(&dev->mode_config.mutex);
2425 }
2426
2427 /**
2428  * drm_mode_attachmode - add a mode to the user mode list
2429  * @dev: DRM device
2430  * @connector: connector to add the mode to
2431  * @mode: mode to add
2432  *
2433  * Add @mode to @connector's user mode list.
2434  */
2435 static void drm_mode_attachmode(struct drm_device *dev,
2436                                 struct drm_connector *connector,
2437                                 struct drm_display_mode *mode)
2438 {
2439         list_add_tail(&mode->head, &connector->user_modes);
2440 }
2441
2442 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
2443                              const struct drm_display_mode *mode)
2444 {
2445         struct drm_connector *connector;
2446         int ret = 0;
2447         struct drm_display_mode *dup_mode, *next;
2448         DRM_LIST_HEAD(list);
2449
2450         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2451                 if (!connector->encoder)
2452                         continue;
2453                 if (connector->encoder->crtc == crtc) {
2454                         dup_mode = drm_mode_duplicate(dev, mode);
2455                         if (!dup_mode) {
2456                                 ret = ENOMEM;
2457                                 goto out;
2458                         }
2459                         list_add_tail(&dup_mode->head, &list);
2460                 }
2461         }
2462
2463         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2464                 if (!connector->encoder)
2465                         continue;
2466                 if (connector->encoder->crtc == crtc)
2467                         list_move_tail(list.next, &connector->user_modes);
2468         }
2469
2470         MPASS(!list_empty(&list));
2471
2472  out:
2473         list_for_each_entry_safe(dup_mode, next, &list, head)
2474                 drm_mode_destroy(dev, dup_mode);
2475
2476         return ret;
2477 }
2478
2479 static int drm_mode_detachmode(struct drm_device *dev,
2480                                struct drm_connector *connector,
2481                                struct drm_display_mode *mode)
2482 {
2483         int found = 0;
2484         int ret = 0;
2485         struct drm_display_mode *match_mode, *t;
2486
2487         list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
2488                 if (drm_mode_equal(match_mode, mode)) {
2489                         list_del(&match_mode->head);
2490                         drm_mode_destroy(dev, match_mode);
2491                         found = 1;
2492                         break;
2493                 }
2494         }
2495
2496         if (!found)
2497                 ret = -EINVAL;
2498
2499         return ret;
2500 }
2501
2502 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
2503 {
2504         struct drm_connector *connector;
2505
2506         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2507                 drm_mode_detachmode(dev, connector, mode);
2508         }
2509         return 0;
2510 }
2511
2512 /**
2513  * drm_fb_attachmode - Attach a user mode to an connector
2514  * @inode: inode from the ioctl
2515  * @filp: file * from the ioctl
2516  * @cmd: cmd from ioctl
2517  * @arg: arg from ioctl
2518  *
2519  * This attaches a user specified mode to an connector.
2520  * Called by the user via ioctl.
2521  *
2522  * RETURNS:
2523  * Zero on success, errno on failure.
2524  */
2525 int drm_mode_attachmode_ioctl(struct drm_device *dev,
2526                               void *data, struct drm_file *file_priv)
2527 {
2528         struct drm_mode_mode_cmd *mode_cmd = data;
2529         struct drm_connector *connector;
2530         struct drm_display_mode *mode;
2531         struct drm_mode_object *obj;
2532         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2533         int ret = 0;
2534
2535         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2536                 return -EINVAL;
2537
2538         sx_xlock(&dev->mode_config.mutex);
2539
2540         obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2541         if (!obj) {
2542                 ret = -EINVAL;
2543                 goto out;
2544         }
2545         connector = obj_to_connector(obj);
2546
2547         mode = drm_mode_create(dev);
2548         if (!mode) {
2549                 ret = -ENOMEM;
2550                 goto out;
2551         }
2552
2553         ret = drm_crtc_convert_umode(mode, umode);
2554         if (ret) {
2555                 DRM_DEBUG_KMS("Invalid mode\n");
2556                 drm_mode_destroy(dev, mode);
2557                 goto out;
2558         }
2559
2560         drm_mode_attachmode(dev, connector, mode);
2561 out:
2562         sx_xunlock(&dev->mode_config.mutex);
2563         return ret;
2564 }
2565
2566
2567 /**
2568  * drm_fb_detachmode - Detach a user specified mode from an connector
2569  * @inode: inode from the ioctl
2570  * @filp: file * from the ioctl
2571  * @cmd: cmd from ioctl
2572  * @arg: arg from ioctl
2573  *
2574  * Called by the user via ioctl.
2575  *
2576  * RETURNS:
2577  * Zero on success, errno on failure.
2578  */
2579 int drm_mode_detachmode_ioctl(struct drm_device *dev,
2580                               void *data, struct drm_file *file_priv)
2581 {
2582         struct drm_mode_object *obj;
2583         struct drm_mode_mode_cmd *mode_cmd = data;
2584         struct drm_connector *connector;
2585         struct drm_display_mode mode;
2586         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2587         int ret = 0;
2588
2589         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2590                 return -EINVAL;
2591
2592         sx_xlock(&dev->mode_config.mutex);
2593
2594         obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2595         if (!obj) {
2596                 ret = -EINVAL;
2597                 goto out;
2598         }
2599         connector = obj_to_connector(obj);
2600
2601         ret = drm_crtc_convert_umode(&mode, umode);
2602         if (ret) {
2603                 DRM_DEBUG_KMS("Invalid mode\n");
2604                 goto out;
2605         }
2606
2607         ret = drm_mode_detachmode(dev, connector, &mode);
2608 out:
2609         sx_xunlock(&dev->mode_config.mutex);
2610         return ret;
2611 }
2612
2613 struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2614                                          const char *name, int num_values)
2615 {
2616         struct drm_property *property = NULL;
2617         int ret;
2618
2619         property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
2620             M_WAITOK | M_ZERO);
2621
2622         if (num_values) {
2623                 property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
2624                     M_WAITOK | M_ZERO);
2625         }
2626
2627         ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
2628         if (ret)
2629                 goto fail;
2630         property->flags = flags;
2631         property->num_values = num_values;
2632         INIT_LIST_HEAD(&property->enum_blob_list);
2633
2634         if (name) {
2635                 strncpy(property->name, name, DRM_PROP_NAME_LEN);
2636                 property->name[DRM_PROP_NAME_LEN-1] = '\0';
2637         }
2638
2639         list_add_tail(&property->head, &dev->mode_config.property_list);
2640         return property;
2641
2642 fail:
2643         free(property->values, DRM_MEM_KMS);
2644         free(property, DRM_MEM_KMS);
2645         return (NULL);
2646 }
2647
2648 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2649                                          const char *name,
2650                                          const struct drm_prop_enum_list *props,
2651                                          int num_values)
2652 {
2653         struct drm_property *property;
2654         int i, ret;
2655
2656         flags |= DRM_MODE_PROP_ENUM;
2657
2658         property = drm_property_create(dev, flags, name, num_values);
2659         if (!property)
2660                 return NULL;
2661
2662         for (i = 0; i < num_values; i++) {
2663                 ret = drm_property_add_enum(property, i,
2664                                       props[i].type,
2665                                       props[i].name);
2666                 if (ret) {
2667                         drm_property_destroy(dev, property);
2668                         return NULL;
2669                 }
2670         }
2671
2672         return property;
2673 }
2674
2675 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2676                                          const char *name,
2677                                          uint64_t min, uint64_t max)
2678 {
2679         struct drm_property *property;
2680
2681         flags |= DRM_MODE_PROP_RANGE;
2682
2683         property = drm_property_create(dev, flags, name, 2);
2684         if (!property)
2685                 return NULL;
2686
2687         property->values[0] = min;
2688         property->values[1] = max;
2689
2690         return property;
2691 }
2692
2693 int drm_property_add_enum(struct drm_property *property, int index,
2694                           uint64_t value, const char *name)
2695 {
2696         struct drm_property_enum *prop_enum;
2697
2698         if (!(property->flags & DRM_MODE_PROP_ENUM))
2699                 return -EINVAL;
2700
2701         if (!list_empty(&property->enum_blob_list)) {
2702                 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2703                         if (prop_enum->value == value) {
2704                                 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2705                                 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2706                                 return 0;
2707                         }
2708                 }
2709         }
2710
2711         prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
2712             M_WAITOK | M_ZERO);
2713
2714         strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2715         prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2716         prop_enum->value = value;
2717
2718         property->values[index] = value;
2719         list_add_tail(&prop_enum->head, &property->enum_blob_list);
2720         return 0;
2721 }
2722
2723 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2724 {
2725         struct drm_property_enum *prop_enum, *pt;
2726
2727         list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2728                 list_del(&prop_enum->head);
2729                 free(prop_enum, DRM_MEM_KMS);
2730         }
2731
2732         if (property->num_values)
2733                 free(property->values, DRM_MEM_KMS);
2734         drm_mode_object_put(dev, &property->base);
2735         list_del(&property->head);
2736         free(property, DRM_MEM_KMS);
2737 }
2738
2739 int drm_connector_attach_property(struct drm_connector *connector,
2740                                struct drm_property *property, uint64_t init_val)
2741 {
2742         int i;
2743
2744         for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2745                 if (connector->property_ids[i] == 0) {
2746                         connector->property_ids[i] = property->base.id;
2747                         connector->property_values[i] = init_val;
2748                         break;
2749                 }
2750         }
2751
2752         if (i == DRM_CONNECTOR_MAX_PROPERTY)
2753                 return -EINVAL;
2754         return 0;
2755 }
2756
2757 int drm_connector_property_set_value(struct drm_connector *connector,
2758                                   struct drm_property *property, uint64_t value)
2759 {
2760         int i;
2761
2762         for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2763                 if (connector->property_ids[i] == property->base.id) {
2764                         connector->property_values[i] = value;
2765                         break;
2766                 }
2767         }
2768
2769         if (i == DRM_CONNECTOR_MAX_PROPERTY)
2770                 return -EINVAL;
2771         return 0;
2772 }
2773
2774 int drm_connector_property_get_value(struct drm_connector *connector,
2775                                   struct drm_property *property, uint64_t *val)
2776 {
2777         int i;
2778
2779         for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
2780                 if (connector->property_ids[i] == property->base.id) {
2781                         *val = connector->property_values[i];
2782                         break;
2783                 }
2784         }
2785
2786         if (i == DRM_CONNECTOR_MAX_PROPERTY)
2787                 return -EINVAL;
2788         return 0;
2789 }
2790
2791 int drm_mode_getproperty_ioctl(struct drm_device *dev,
2792                                void *data, struct drm_file *file_priv)
2793 {
2794         struct drm_mode_object *obj;
2795         struct drm_mode_get_property *out_resp = data;
2796         struct drm_property *property;
2797         int enum_count = 0;
2798         int blob_count = 0;
2799         int value_count = 0;
2800         int ret = 0, i;
2801         int copied;
2802         struct drm_property_enum *prop_enum;
2803         struct drm_mode_property_enum __user *enum_ptr;
2804         struct drm_property_blob *prop_blob;
2805         uint32_t *blob_id_ptr;
2806         uint64_t *values_ptr;
2807         uint32_t *blob_length_ptr;
2808
2809         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2810                 return -EINVAL;
2811
2812         sx_xlock(&dev->mode_config.mutex);
2813         obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
2814         if (!obj) {
2815                 ret = -EINVAL;
2816                 goto done;
2817         }
2818         property = obj_to_property(obj);
2819
2820         if (property->flags & DRM_MODE_PROP_ENUM) {
2821                 list_for_each_entry(prop_enum, &property->enum_blob_list, head)
2822                         enum_count++;
2823         } else if (property->flags & DRM_MODE_PROP_BLOB) {
2824                 list_for_each_entry(prop_blob, &property->enum_blob_list, head)
2825                         blob_count++;
2826         }
2827
2828         value_count = property->num_values;
2829
2830         strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
2831         out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
2832         out_resp->flags = property->flags;
2833
2834         if ((out_resp->count_values >= value_count) && value_count) {
2835                 values_ptr = (uint64_t *)(uintptr_t)out_resp->values_ptr;
2836                 for (i = 0; i < value_count; i++) {
2837                         if (copyout(&property->values[i], values_ptr + i, sizeof(uint64_t))) {
2838                                 ret = -EFAULT;
2839                                 goto done;
2840                         }
2841                 }
2842         }
2843         out_resp->count_values = value_count;
2844
2845         if (property->flags & DRM_MODE_PROP_ENUM) {
2846                 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
2847                         copied = 0;
2848                         enum_ptr = (struct drm_mode_property_enum *)(uintptr_t)out_resp->enum_blob_ptr;
2849                         list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2850
2851                                 if (copyout(&prop_enum->value, &enum_ptr[copied].value, sizeof(uint64_t))) {
2852                                         ret = -EFAULT;
2853                                         goto done;
2854                                 }
2855
2856                                 if (copyout(&prop_enum->name,
2857                                     &enum_ptr[copied].name,DRM_PROP_NAME_LEN)) {
2858                                         ret = -EFAULT;
2859                                         goto done;
2860                                 }
2861                                 copied++;
2862                         }
2863                 }
2864                 out_resp->count_enum_blobs = enum_count;
2865         }
2866
2867         if (property->flags & DRM_MODE_PROP_BLOB) {
2868                 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
2869                         copied = 0;
2870                         blob_id_ptr = (uint32_t *)(uintptr_t)out_resp->enum_blob_ptr;
2871                         blob_length_ptr = (uint32_t *)(uintptr_t)out_resp->values_ptr;
2872
2873                         list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
2874                                 if (copyout(&prop_blob->base.id,
2875                                     blob_id_ptr + copied, sizeof(uint32_t))) {
2876                                         ret = -EFAULT;
2877                                         goto done;
2878                                 }
2879
2880                                 if (copyout(&prop_blob->length,
2881                                     blob_length_ptr + copied, sizeof(uint32_t))) {
2882                                         ret = -EFAULT;
2883                                         goto done;
2884                                 }
2885
2886                                 copied++;
2887                         }
2888                 }
2889                 out_resp->count_enum_blobs = blob_count;
2890         }
2891 done:
2892         sx_xunlock(&dev->mode_config.mutex);
2893         return ret;
2894 }
2895
2896 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
2897                                                           void *data)
2898 {
2899         struct drm_property_blob *blob;
2900         int ret;
2901
2902         if (!length || !data)
2903                 return NULL;
2904
2905         blob = malloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS,
2906             M_WAITOK | M_ZERO);
2907
2908         ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
2909         if (ret) {
2910                 free(blob, DRM_MEM_KMS);
2911                 return (NULL);
2912         }
2913
2914         blob->length = length;
2915
2916         memcpy(blob->data, data, length);
2917
2918         list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
2919         return blob;
2920 }
2921
2922 static void drm_property_destroy_blob(struct drm_device *dev,
2923                                struct drm_property_blob *blob)
2924 {
2925         drm_mode_object_put(dev, &blob->base);
2926         list_del(&blob->head);
2927         free(blob, DRM_MEM_KMS);
2928 }
2929
2930 int drm_mode_getblob_ioctl(struct drm_device *dev,
2931                            void *data, struct drm_file *file_priv)
2932 {
2933         struct drm_mode_object *obj;
2934         struct drm_mode_get_blob *out_resp = data;
2935         struct drm_property_blob *blob;
2936         int ret = 0;
2937         void *blob_ptr;
2938
2939         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2940                 return -EINVAL;
2941
2942         sx_xlock(&dev->mode_config.mutex);
2943         obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
2944         if (!obj) {
2945                 ret = -EINVAL;
2946                 goto done;
2947         }
2948         blob = obj_to_blob(obj);
2949
2950         if (out_resp->length == blob->length) {
2951                 blob_ptr = (void *)(unsigned long)out_resp->data;
2952                 if (copyout(blob->data, blob_ptr, blob->length)){
2953                         ret = -EFAULT;
2954                         goto done;
2955                 }
2956         }
2957         out_resp->length = blob->length;
2958
2959 done:
2960         sx_xunlock(&dev->mode_config.mutex);
2961         return ret;
2962 }
2963
2964 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
2965                                             struct edid *edid)
2966 {
2967         struct drm_device *dev = connector->dev;
2968         int ret = 0, size;
2969
2970         if (connector->edid_blob_ptr)
2971                 drm_property_destroy_blob(dev, connector->edid_blob_ptr);
2972
2973         /* Delete edid, when there is none. */
2974         if (!edid) {
2975                 connector->edid_blob_ptr = NULL;
2976                 ret = drm_connector_property_set_value(connector, dev->mode_config.edid_property, 0);
2977                 return ret;
2978         }
2979
2980         size = EDID_LENGTH * (1 + edid->extensions);
2981         connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
2982                                                             size, edid);
2983
2984         ret = drm_connector_property_set_value(connector,
2985                                                dev->mode_config.edid_property,
2986                                                connector->edid_blob_ptr->base.id);
2987
2988         return ret;
2989 }
2990
2991 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
2992                                        void *data, struct drm_file *file_priv)
2993 {
2994         struct drm_mode_connector_set_property *out_resp = data;
2995         struct drm_mode_object *obj;
2996         struct drm_property *property;
2997         struct drm_connector *connector;
2998         int ret = -EINVAL;
2999         int i;
3000
3001         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3002                 return -EINVAL;
3003
3004         sx_xlock(&dev->mode_config.mutex);
3005
3006         obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
3007         if (!obj) {
3008                 goto out;
3009         }
3010         connector = obj_to_connector(obj);
3011
3012         for (i = 0; i < DRM_CONNECTOR_MAX_PROPERTY; i++) {
3013                 if (connector->property_ids[i] == out_resp->prop_id)
3014                         break;
3015         }
3016
3017         if (i == DRM_CONNECTOR_MAX_PROPERTY) {
3018                 goto out;
3019         }
3020
3021         obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
3022         if (!obj) {
3023                 goto out;
3024         }
3025         property = obj_to_property(obj);
3026
3027         if (property->flags & DRM_MODE_PROP_IMMUTABLE)
3028                 goto out;
3029
3030         if (property->flags & DRM_MODE_PROP_RANGE) {
3031                 if (out_resp->value < property->values[0])
3032                         goto out;
3033
3034                 if (out_resp->value > property->values[1])
3035                         goto out;
3036         } else {
3037                 int found = 0;
3038                 for (i = 0; i < property->num_values; i++) {
3039                         if (property->values[i] == out_resp->value) {
3040                                 found = 1;
3041                                 break;
3042                         }
3043                 }
3044                 if (!found) {
3045                         goto out;
3046                 }
3047         }
3048
3049         /* Do DPMS ourselves */
3050         if (property == connector->dev->mode_config.dpms_property) {
3051                 if (connector->funcs->dpms)
3052                         (*connector->funcs->dpms)(connector, (int) out_resp->value);
3053                 ret = 0;
3054         } else if (connector->funcs->set_property)
3055                 ret = connector->funcs->set_property(connector, property, out_resp->value);
3056
3057         /* store the property value if successful */
3058         if (!ret)
3059                 drm_connector_property_set_value(connector, property, out_resp->value);
3060 out:
3061         sx_xunlock(&dev->mode_config.mutex);
3062         return ret;
3063 }
3064
3065 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
3066                                       struct drm_encoder *encoder)
3067 {
3068         int i;
3069
3070         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3071                 if (connector->encoder_ids[i] == 0) {
3072                         connector->encoder_ids[i] = encoder->base.id;
3073                         return 0;
3074                 }
3075         }
3076         return -ENOMEM;
3077 }
3078
3079 void drm_mode_connector_detach_encoder(struct drm_connector *connector,
3080                                     struct drm_encoder *encoder)
3081 {
3082         int i;
3083         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3084                 if (connector->encoder_ids[i] == encoder->base.id) {
3085                         connector->encoder_ids[i] = 0;
3086                         if (connector->encoder == encoder)
3087                                 connector->encoder = NULL;
3088                         break;
3089                 }
3090         }
3091 }
3092
3093 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
3094                                   int gamma_size)
3095 {
3096         crtc->gamma_size = gamma_size;
3097
3098         crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
3099             DRM_MEM_KMS, M_WAITOK | M_ZERO);
3100
3101         return 0;
3102 }
3103
3104 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
3105                              void *data, struct drm_file *file_priv)
3106 {
3107         struct drm_mode_crtc_lut *crtc_lut = data;
3108         struct drm_mode_object *obj;
3109         struct drm_crtc *crtc;
3110         void *r_base, *g_base, *b_base;
3111         int size;
3112         int ret = 0;
3113
3114         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3115                 return -EINVAL;
3116
3117         sx_xlock(&dev->mode_config.mutex);
3118         obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3119         if (!obj) {
3120                 ret = -EINVAL;
3121                 goto out;
3122         }
3123         crtc = obj_to_crtc(obj);
3124
3125         /* memcpy into gamma store */
3126         if (crtc_lut->gamma_size != crtc->gamma_size) {
3127                 ret = -EINVAL;
3128                 goto out;
3129         }
3130
3131         size = crtc_lut->gamma_size * (sizeof(uint16_t));
3132         r_base = crtc->gamma_store;
3133         if (copyin((void *)(uintptr_t)crtc_lut->red, r_base, size)) {
3134                 ret = -EFAULT;
3135                 goto out;
3136         }
3137
3138         g_base = (char *)r_base + size;
3139         if (copyin((void *)(uintptr_t)crtc_lut->green, g_base, size)) {
3140                 ret = -EFAULT;
3141                 goto out;
3142         }
3143
3144         b_base = (char *)g_base + size;
3145         if (copyin((void *)(uintptr_t)crtc_lut->blue, b_base, size)) {
3146                 ret = -EFAULT;
3147                 goto out;
3148         }
3149
3150         crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
3151
3152 out:
3153         sx_xunlock(&dev->mode_config.mutex);
3154         return ret;
3155
3156 }
3157
3158 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
3159                              void *data, struct drm_file *file_priv)
3160 {
3161         struct drm_mode_crtc_lut *crtc_lut = data;
3162         struct drm_mode_object *obj;
3163         struct drm_crtc *crtc;
3164         void *r_base, *g_base, *b_base;
3165         int size;
3166         int ret = 0;
3167
3168         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3169                 return -EINVAL;
3170
3171         sx_xlock(&dev->mode_config.mutex);
3172         obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3173         if (!obj) {
3174                 ret = -EINVAL;
3175                 goto out;
3176         }
3177         crtc = obj_to_crtc(obj);
3178
3179         /* memcpy into gamma store */
3180         if (crtc_lut->gamma_size != crtc->gamma_size) {
3181                 ret = -EINVAL;
3182                 goto out;
3183         }
3184
3185         size = crtc_lut->gamma_size * (sizeof(uint16_t));
3186         r_base = crtc->gamma_store;
3187         if (copyout(r_base, (void *)(uintptr_t)crtc_lut->red, size)) {
3188                 ret = -EFAULT;
3189                 goto out;
3190         }
3191
3192         g_base = (char *)r_base + size;
3193         if (copyout(g_base, (void *)(uintptr_t)crtc_lut->green, size)) {
3194                 ret = -EFAULT;
3195                 goto out;
3196         }
3197
3198         b_base = (char *)g_base + size;
3199         if (copyout(b_base, (void *)(uintptr_t)crtc_lut->blue, size)) {
3200                 ret = -EFAULT;
3201                 goto out;
3202         }
3203 out:
3204         sx_xunlock(&dev->mode_config.mutex);
3205         return ret;
3206 }
3207
3208 static void
3209 drm_kms_free(void *arg)
3210 {
3211
3212         free(arg, DRM_MEM_KMS);
3213 }
3214
3215 int drm_mode_page_flip_ioctl(struct drm_device *dev, void *data,
3216     struct drm_file *file_priv)
3217 {
3218         struct drm_mode_crtc_page_flip *page_flip = data;
3219         struct drm_mode_object *obj;
3220         struct drm_crtc *crtc;
3221         struct drm_framebuffer *fb;
3222         struct drm_pending_vblank_event *e = NULL;
3223         int ret = EINVAL;
3224
3225         if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
3226             page_flip->reserved != 0)
3227                 return (EINVAL);
3228
3229         sx_xlock(&dev->mode_config.mutex);
3230         obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
3231         if (!obj)
3232                 goto out;
3233         crtc = obj_to_crtc(obj);
3234
3235         if (crtc->fb == NULL) {
3236                 /* The framebuffer is currently unbound, presumably
3237                  * due to a hotplug event, that userspace has not
3238                  * yet discovered.
3239                  */
3240                 ret = EBUSY;
3241                 goto out;
3242         }
3243
3244         if (crtc->funcs->page_flip == NULL)
3245                 goto out;
3246
3247         obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
3248         if (!obj)
3249                 goto out;
3250         fb = obj_to_fb(obj);
3251
3252         if (crtc->mode.hdisplay > fb->width ||
3253             crtc->mode.vdisplay > fb->height ||
3254             crtc->x > fb->width - crtc->mode.hdisplay ||
3255             crtc->y > fb->height - crtc->mode.vdisplay) {
3256                 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d.\n",
3257                               fb->width, fb->height,
3258                               crtc->mode.hdisplay, crtc->mode.vdisplay,
3259                               crtc->x, crtc->y);
3260                 ret = ENOSPC;
3261                 goto out;
3262         }
3263
3264         if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3265                 ret = ENOMEM;
3266                 mtx_lock(&dev->event_lock);
3267                 if (file_priv->event_space < sizeof e->event) {
3268                         mtx_unlock(&dev->event_lock);
3269                         goto out;
3270                 }
3271                 file_priv->event_space -= sizeof e->event;
3272                 mtx_unlock(&dev->event_lock);
3273
3274                 e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
3275
3276                 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
3277                 e->event.base.length = sizeof e->event;
3278                 e->event.user_data = page_flip->user_data;
3279                 e->base.event = &e->event.base;
3280                 e->base.file_priv = file_priv;
3281                 e->base.destroy =
3282                         (void (*) (struct drm_pending_event *))drm_kms_free;
3283         }
3284
3285         ret = -crtc->funcs->page_flip(crtc, fb, e);
3286         if (ret != 0) {
3287                 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3288                         mtx_lock(&dev->event_lock);
3289                         file_priv->event_space += sizeof e->event;
3290                         mtx_unlock(&dev->event_lock);
3291                         free(e, DRM_MEM_KMS);
3292                 }
3293         }
3294
3295 out:
3296         sx_xunlock(&dev->mode_config.mutex);
3297         CTR3(KTR_DRM, "page_flip_ioctl %d %d %d", curproc->p_pid,
3298             page_flip->crtc_id, ret);
3299         return (ret);
3300 }
3301
3302 void drm_mode_config_reset(struct drm_device *dev)
3303 {
3304         struct drm_crtc *crtc;
3305         struct drm_encoder *encoder;
3306         struct drm_connector *connector;
3307
3308         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
3309                 if (crtc->funcs->reset)
3310                         crtc->funcs->reset(crtc);
3311
3312         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
3313                 if (encoder->funcs->reset)
3314                         encoder->funcs->reset(encoder);
3315
3316         list_for_each_entry(connector, &dev->mode_config.connector_list, head)
3317                 if (connector->funcs->reset)
3318                         connector->funcs->reset(connector);
3319 }
3320
3321 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
3322                                void *data, struct drm_file *file_priv)
3323 {
3324         struct drm_mode_create_dumb *args = data;
3325
3326         if (!dev->driver->dumb_create)
3327                 return -ENOTSUP;
3328         return dev->driver->dumb_create(file_priv, dev, args);
3329 }
3330
3331 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
3332                              void *data, struct drm_file *file_priv)
3333 {
3334         struct drm_mode_map_dumb *args = data;
3335
3336         /* call driver ioctl to get mmap offset */
3337         if (!dev->driver->dumb_map_offset)
3338                 return -ENOTSUP;
3339
3340         return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
3341 }
3342
3343 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
3344                                 void *data, struct drm_file *file_priv)
3345 {
3346         struct drm_mode_destroy_dumb *args = data;
3347
3348         if (!dev->driver->dumb_destroy)
3349                 return -ENOTSUP;
3350
3351         return dev->driver->dumb_destroy(file_priv, dev, args->handle);
3352 }
3353
3354 /*
3355  * Just need to support RGB formats here for compat with code that doesn't
3356  * use pixel formats directly yet.
3357  */
3358 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
3359                           int *bpp)
3360 {
3361         switch (format) {
3362         case DRM_FORMAT_RGB332:
3363         case DRM_FORMAT_BGR233:
3364                 *depth = 8;
3365                 *bpp = 8;
3366                 break;
3367         case DRM_FORMAT_XRGB1555:
3368         case DRM_FORMAT_XBGR1555:
3369         case DRM_FORMAT_RGBX5551:
3370         case DRM_FORMAT_BGRX5551:
3371         case DRM_FORMAT_ARGB1555:
3372         case DRM_FORMAT_ABGR1555:
3373         case DRM_FORMAT_RGBA5551:
3374         case DRM_FORMAT_BGRA5551:
3375                 *depth = 15;
3376                 *bpp = 16;
3377                 break;
3378         case DRM_FORMAT_RGB565:
3379         case DRM_FORMAT_BGR565:
3380                 *depth = 16;
3381                 *bpp = 16;
3382                 break;
3383         case DRM_FORMAT_RGB888:
3384         case DRM_FORMAT_BGR888:
3385                 *depth = 24;
3386                 *bpp = 24;
3387                 break;
3388         case DRM_FORMAT_XRGB8888:
3389         case DRM_FORMAT_XBGR8888:
3390         case DRM_FORMAT_RGBX8888:
3391         case DRM_FORMAT_BGRX8888:
3392                 *depth = 24;
3393                 *bpp = 32;
3394                 break;
3395         case DRM_FORMAT_XRGB2101010:
3396         case DRM_FORMAT_XBGR2101010:
3397         case DRM_FORMAT_RGBX1010102:
3398         case DRM_FORMAT_BGRX1010102:
3399         case DRM_FORMAT_ARGB2101010:
3400         case DRM_FORMAT_ABGR2101010:
3401         case DRM_FORMAT_RGBA1010102:
3402         case DRM_FORMAT_BGRA1010102:
3403                 *depth = 30;
3404                 *bpp = 32;
3405                 break;
3406         case DRM_FORMAT_ARGB8888:
3407         case DRM_FORMAT_ABGR8888:
3408         case DRM_FORMAT_RGBA8888:
3409         case DRM_FORMAT_BGRA8888:
3410                 *depth = 32;
3411                 *bpp = 32;
3412                 break;
3413         default:
3414                 DRM_DEBUG_KMS("unsupported pixel format\n");
3415                 *depth = 0;
3416                 *bpp = 0;
3417                 break;
3418         }
3419 }