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