Merge branch 'vendor/EE'
[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         ret = -dev->mode_config.funcs->fb_create(dev, file_priv, &r, &fb);
2189         if (ret != 0) {
2190                 DRM_ERROR("could not create framebuffer, error %d\n", ret);
2191                 goto out;
2192         }
2193
2194         or->fb_id = fb->base.id;
2195         list_add(&fb->filp_head, &file_priv->fbs);
2196         DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2197
2198 out:
2199         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2200         return ret;
2201 }
2202
2203 static int format_check(const struct drm_mode_fb_cmd2 *r)
2204 {
2205         uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
2206
2207         switch (format) {
2208         case DRM_FORMAT_C8:
2209         case DRM_FORMAT_RGB332:
2210         case DRM_FORMAT_BGR233:
2211         case DRM_FORMAT_XRGB4444:
2212         case DRM_FORMAT_XBGR4444:
2213         case DRM_FORMAT_RGBX4444:
2214         case DRM_FORMAT_BGRX4444:
2215         case DRM_FORMAT_ARGB4444:
2216         case DRM_FORMAT_ABGR4444:
2217         case DRM_FORMAT_RGBA4444:
2218         case DRM_FORMAT_BGRA4444:
2219         case DRM_FORMAT_XRGB1555:
2220         case DRM_FORMAT_XBGR1555:
2221         case DRM_FORMAT_RGBX5551:
2222         case DRM_FORMAT_BGRX5551:
2223         case DRM_FORMAT_ARGB1555:
2224         case DRM_FORMAT_ABGR1555:
2225         case DRM_FORMAT_RGBA5551:
2226         case DRM_FORMAT_BGRA5551:
2227         case DRM_FORMAT_RGB565:
2228         case DRM_FORMAT_BGR565:
2229         case DRM_FORMAT_RGB888:
2230         case DRM_FORMAT_BGR888:
2231         case DRM_FORMAT_XRGB8888:
2232         case DRM_FORMAT_XBGR8888:
2233         case DRM_FORMAT_RGBX8888:
2234         case DRM_FORMAT_BGRX8888:
2235         case DRM_FORMAT_ARGB8888:
2236         case DRM_FORMAT_ABGR8888:
2237         case DRM_FORMAT_RGBA8888:
2238         case DRM_FORMAT_BGRA8888:
2239         case DRM_FORMAT_XRGB2101010:
2240         case DRM_FORMAT_XBGR2101010:
2241         case DRM_FORMAT_RGBX1010102:
2242         case DRM_FORMAT_BGRX1010102:
2243         case DRM_FORMAT_ARGB2101010:
2244         case DRM_FORMAT_ABGR2101010:
2245         case DRM_FORMAT_RGBA1010102:
2246         case DRM_FORMAT_BGRA1010102:
2247         case DRM_FORMAT_YUYV:
2248         case DRM_FORMAT_YVYU:
2249         case DRM_FORMAT_UYVY:
2250         case DRM_FORMAT_VYUY:
2251         case DRM_FORMAT_AYUV:
2252         case DRM_FORMAT_NV12:
2253         case DRM_FORMAT_NV21:
2254         case DRM_FORMAT_NV16:
2255         case DRM_FORMAT_NV61:
2256         case DRM_FORMAT_NV24:
2257         case DRM_FORMAT_NV42:
2258         case DRM_FORMAT_YUV410:
2259         case DRM_FORMAT_YVU410:
2260         case DRM_FORMAT_YUV411:
2261         case DRM_FORMAT_YVU411:
2262         case DRM_FORMAT_YUV420:
2263         case DRM_FORMAT_YVU420:
2264         case DRM_FORMAT_YUV422:
2265         case DRM_FORMAT_YVU422:
2266         case DRM_FORMAT_YUV444:
2267         case DRM_FORMAT_YVU444:
2268                 return 0;
2269         default:
2270                 return -EINVAL;
2271         }
2272 }
2273
2274 static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
2275 {
2276         int ret, hsub, vsub, num_planes, i;
2277
2278         ret = format_check(r);
2279         if (ret) {
2280                 DRM_DEBUG_KMS("bad framebuffer format 0x%08x\n", r->pixel_format);
2281                 return ret;
2282         }
2283
2284         hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
2285         vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
2286         num_planes = drm_format_num_planes(r->pixel_format);
2287
2288         if (r->width == 0 || r->width % hsub) {
2289                 DRM_DEBUG_KMS("bad framebuffer width %u\n", r->height);
2290                 return -EINVAL;
2291         }
2292
2293         if (r->height == 0 || r->height % vsub) {
2294                 DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
2295                 return -EINVAL;
2296         }
2297
2298         for (i = 0; i < num_planes; i++) {
2299                 unsigned int width = r->width / (i != 0 ? hsub : 1);
2300                 unsigned int height = r->height / (i != 0 ? vsub : 1);
2301                 unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
2302
2303                 if (!r->handles[i]) {
2304                         DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
2305                         return -EINVAL;
2306                 }
2307
2308                 if ((uint64_t) width * cpp > UINT_MAX)
2309                         return -ERANGE;
2310
2311                 if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
2312                         return -ERANGE;
2313
2314                 if (r->pitches[i] < width * cpp) {
2315                         DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
2316                         return -EINVAL;
2317                 }
2318         }
2319
2320         return 0;
2321 }
2322
2323 /**
2324  * drm_mode_addfb2 - add an FB to the graphics configuration
2325  * @inode: inode from the ioctl
2326  * @filp: file * from the ioctl
2327  * @cmd: cmd from ioctl
2328  * @arg: arg from ioctl
2329  *
2330  * LOCKING:
2331  * Takes mode config lock.
2332  *
2333  * Add a new FB to the specified CRTC, given a user request with format.
2334  *
2335  * Called by the user via ioctl.
2336  *
2337  * RETURNS:
2338  * Zero on success, errno on failure.
2339  */
2340 int drm_mode_addfb2(struct drm_device *dev,
2341                     void *data, struct drm_file *file_priv)
2342 {
2343         struct drm_mode_fb_cmd2 *r = data;
2344         struct drm_mode_config *config = &dev->mode_config;
2345         struct drm_framebuffer *fb;
2346         int ret;
2347
2348         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2349                 return -EINVAL;
2350
2351         if (r->flags & ~DRM_MODE_FB_INTERLACED) {
2352                 DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
2353                 return -EINVAL;
2354         }
2355
2356         if ((config->min_width > r->width) || (r->width > config->max_width)) {
2357                 DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
2358                           r->width, config->min_width, config->max_width);
2359                 return -EINVAL;
2360         }
2361         if ((config->min_height > r->height) || (r->height > config->max_height)) {
2362                 DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
2363                           r->height, config->min_height, config->max_height);
2364                 return -EINVAL;
2365         }
2366
2367         ret = framebuffer_check(r);
2368         if (ret)
2369                 return ret;
2370
2371         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2372
2373         ret = -dev->mode_config.funcs->fb_create(dev, file_priv, r, &fb);
2374         if (ret != 0) {
2375                 DRM_ERROR("could not create framebuffer, error %d\n", ret);
2376                 ret = PTR_ERR(fb);
2377                 goto out;
2378         }
2379
2380         r->fb_id = fb->base.id;
2381         list_add(&fb->filp_head, &file_priv->fbs);
2382         DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
2383
2384 out:
2385         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2386         return ret;
2387 }
2388
2389 /**
2390  * drm_mode_rmfb - remove an FB from the configuration
2391  * @inode: inode from the ioctl
2392  * @filp: file * from the ioctl
2393  * @cmd: cmd from ioctl
2394  * @arg: arg from ioctl
2395  *
2396  * LOCKING:
2397  * Takes mode config lock.
2398  *
2399  * Remove the FB specified by the user.
2400  *
2401  * Called by the user via ioctl.
2402  *
2403  * RETURNS:
2404  * Zero on success, errno on failure.
2405  */
2406 int drm_mode_rmfb(struct drm_device *dev,
2407                    void *data, struct drm_file *file_priv)
2408 {
2409         struct drm_mode_object *obj;
2410         struct drm_framebuffer *fb = NULL;
2411         struct drm_framebuffer *fbl = NULL;
2412         uint32_t *id = data;
2413         int ret = 0;
2414         int found = 0;
2415
2416         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2417                 return -EINVAL;
2418
2419         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2420         obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
2421         /* TODO check that we really get a framebuffer back. */
2422         if (!obj) {
2423                 ret = -EINVAL;
2424                 goto out;
2425         }
2426         fb = obj_to_fb(obj);
2427
2428         list_for_each_entry(fbl, &file_priv->fbs, filp_head)
2429                 if (fb == fbl)
2430                         found = 1;
2431
2432         if (!found) {
2433                 ret = -EINVAL;
2434                 goto out;
2435         }
2436
2437         drm_framebuffer_remove(fb);
2438
2439 out:
2440         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2441         return ret;
2442 }
2443
2444 /**
2445  * drm_mode_getfb - get FB info
2446  * @inode: inode from the ioctl
2447  * @filp: file * from the ioctl
2448  * @cmd: cmd from ioctl
2449  * @arg: arg from ioctl
2450  *
2451  * LOCKING:
2452  * Takes mode config lock.
2453  *
2454  * Lookup the FB given its ID and return info about it.
2455  *
2456  * Called by the user via ioctl.
2457  *
2458  * RETURNS:
2459  * Zero on success, errno on failure.
2460  */
2461 int drm_mode_getfb(struct drm_device *dev,
2462                    void *data, struct drm_file *file_priv)
2463 {
2464         struct drm_mode_fb_cmd *r = data;
2465         struct drm_mode_object *obj;
2466         struct drm_framebuffer *fb;
2467         int ret = 0;
2468
2469         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2470                 return -EINVAL;
2471
2472         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2473         obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2474         if (!obj) {
2475                 ret = -EINVAL;
2476                 goto out;
2477         }
2478         fb = obj_to_fb(obj);
2479
2480         r->height = fb->height;
2481         r->width = fb->width;
2482         r->depth = fb->depth;
2483         r->bpp = fb->bits_per_pixel;
2484         r->pitch = fb->pitches[0];
2485         fb->funcs->create_handle(fb, file_priv, &r->handle);
2486
2487 out:
2488         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2489         return ret;
2490 }
2491
2492 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
2493                            void *data, struct drm_file *file_priv)
2494 {
2495         struct drm_clip_rect __user *clips_ptr;
2496         struct drm_clip_rect *clips = NULL;
2497         struct drm_mode_fb_dirty_cmd *r = data;
2498         struct drm_mode_object *obj;
2499         struct drm_framebuffer *fb;
2500         unsigned flags;
2501         int num_clips;
2502         int ret;
2503
2504         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2505                 return -EINVAL;
2506
2507         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2508         obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
2509         if (!obj) {
2510                 ret = -EINVAL;
2511                 goto out_err1;
2512         }
2513         fb = obj_to_fb(obj);
2514
2515         num_clips = r->num_clips;
2516         clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
2517
2518         if (!num_clips != !clips_ptr) {
2519                 ret = -EINVAL;
2520                 goto out_err1;
2521         }
2522
2523         flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
2524
2525         /* If userspace annotates copy, clips must come in pairs */
2526         if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
2527                 ret = -EINVAL;
2528                 goto out_err1;
2529         }
2530
2531         if (num_clips && clips_ptr) {
2532                 if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
2533                         ret = -EINVAL;
2534                         goto out_err1;
2535                 }
2536                 clips = kmalloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
2537                     M_WAITOK | M_ZERO);
2538                 if (!clips) {
2539                         ret = -ENOMEM;
2540                         goto out_err1;
2541                 }
2542
2543                 ret = copy_from_user(clips, clips_ptr,
2544                                      num_clips * sizeof(*clips));
2545                 if (ret) {
2546                         ret = -EFAULT;
2547                         goto out_err2;
2548                 }
2549         }
2550
2551         if (fb->funcs->dirty) {
2552                 ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
2553                                        clips, num_clips);
2554         } else {
2555                 ret = -ENOSYS;
2556                 goto out_err2;
2557         }
2558
2559 out_err2:
2560         drm_free(clips, DRM_MEM_KMS);
2561 out_err1:
2562         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2563         return ret;
2564 }
2565
2566
2567 /**
2568  * drm_fb_release - remove and free the FBs on this file
2569  * @filp: file * from the ioctl
2570  *
2571  * LOCKING:
2572  * Takes mode config lock.
2573  *
2574  * Destroy all the FBs associated with @filp.
2575  *
2576  * Called by the user via ioctl.
2577  *
2578  * RETURNS:
2579  * Zero on success, errno on failure.
2580  */
2581 void drm_fb_release(struct drm_file *priv)
2582 {
2583 #if 1
2584         struct drm_device *dev = priv->dev;
2585 #else
2586         struct drm_device *dev = priv->minor->dev;
2587 #endif
2588         struct drm_framebuffer *fb, *tfb;
2589
2590         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2591         list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
2592                 drm_framebuffer_remove(fb);
2593         }
2594         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2595 }
2596
2597 /**
2598  * drm_mode_attachmode - add a mode to the user mode list
2599  * @dev: DRM device
2600  * @connector: connector to add the mode to
2601  * @mode: mode to add
2602  *
2603  * Add @mode to @connector's user mode list.
2604  */
2605 static void drm_mode_attachmode(struct drm_device *dev,
2606                                 struct drm_connector *connector,
2607                                 struct drm_display_mode *mode)
2608 {
2609         list_add_tail(&mode->head, &connector->user_modes);
2610 }
2611
2612 int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
2613                              const struct drm_display_mode *mode)
2614 {
2615         struct drm_connector *connector;
2616         int ret = 0;
2617         struct drm_display_mode *dup_mode, *next;
2618         LINUX_LIST_HEAD(list);
2619
2620         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2621                 if (!connector->encoder)
2622                         continue;
2623                 if (connector->encoder->crtc == crtc) {
2624                         dup_mode = drm_mode_duplicate(dev, mode);
2625                         if (!dup_mode) {
2626                                 ret = -ENOMEM;
2627                                 goto out;
2628                         }
2629                         list_add_tail(&dup_mode->head, &list);
2630                 }
2631         }
2632
2633         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2634                 if (!connector->encoder)
2635                         continue;
2636                 if (connector->encoder->crtc == crtc)
2637                         list_move_tail(list.next, &connector->user_modes);
2638         }
2639
2640         WARN_ON(!list_empty(&list));
2641
2642  out:
2643         list_for_each_entry_safe(dup_mode, next, &list, head)
2644                 drm_mode_destroy(dev, dup_mode);
2645
2646         return ret;
2647 }
2648 EXPORT_SYMBOL(drm_mode_attachmode_crtc);
2649
2650 static int drm_mode_detachmode(struct drm_device *dev,
2651                                struct drm_connector *connector,
2652                                struct drm_display_mode *mode)
2653 {
2654         int found = 0;
2655         int ret = 0;
2656         struct drm_display_mode *match_mode, *t;
2657
2658         list_for_each_entry_safe(match_mode, t, &connector->user_modes, head) {
2659                 if (drm_mode_equal(match_mode, mode)) {
2660                         list_del(&match_mode->head);
2661                         drm_mode_destroy(dev, match_mode);
2662                         found = 1;
2663                         break;
2664                 }
2665         }
2666
2667         if (!found)
2668                 ret = -EINVAL;
2669
2670         return ret;
2671 }
2672
2673 int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode)
2674 {
2675         struct drm_connector *connector;
2676
2677         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2678                 drm_mode_detachmode(dev, connector, mode);
2679         }
2680         return 0;
2681 }
2682 EXPORT_SYMBOL(drm_mode_detachmode_crtc);
2683
2684 /**
2685  * drm_fb_attachmode - Attach a user mode to an connector
2686  * @inode: inode from the ioctl
2687  * @filp: file * from the ioctl
2688  * @cmd: cmd from ioctl
2689  * @arg: arg from ioctl
2690  *
2691  * This attaches a user specified mode to an connector.
2692  * Called by the user via ioctl.
2693  *
2694  * RETURNS:
2695  * Zero on success, errno on failure.
2696  */
2697 int drm_mode_attachmode_ioctl(struct drm_device *dev,
2698                               void *data, struct drm_file *file_priv)
2699 {
2700         struct drm_mode_mode_cmd *mode_cmd = data;
2701         struct drm_connector *connector;
2702         struct drm_display_mode *mode;
2703         struct drm_mode_object *obj;
2704         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2705         int ret;
2706
2707         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2708                 return -EINVAL;
2709
2710         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2711
2712         obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2713         if (!obj) {
2714                 ret = -EINVAL;
2715                 goto out;
2716         }
2717         connector = obj_to_connector(obj);
2718
2719         mode = drm_mode_create(dev);
2720         if (!mode) {
2721                 ret = -ENOMEM;
2722                 goto out;
2723         }
2724
2725         ret = drm_crtc_convert_umode(mode, umode);
2726         if (ret) {
2727                 DRM_DEBUG_KMS("Invalid mode\n");
2728                 drm_mode_destroy(dev, mode);
2729                 goto out;
2730         }
2731
2732         drm_mode_attachmode(dev, connector, mode);
2733 out:
2734         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2735         return ret;
2736 }
2737
2738
2739 /**
2740  * drm_fb_detachmode - Detach a user specified mode from an connector
2741  * @inode: inode from the ioctl
2742  * @filp: file * from the ioctl
2743  * @cmd: cmd from ioctl
2744  * @arg: arg from ioctl
2745  *
2746  * Called by the user via ioctl.
2747  *
2748  * RETURNS:
2749  * Zero on success, errno on failure.
2750  */
2751 int drm_mode_detachmode_ioctl(struct drm_device *dev,
2752                               void *data, struct drm_file *file_priv)
2753 {
2754         struct drm_mode_object *obj;
2755         struct drm_mode_mode_cmd *mode_cmd = data;
2756         struct drm_connector *connector;
2757         struct drm_display_mode mode;
2758         struct drm_mode_modeinfo *umode = &mode_cmd->mode;
2759         int ret;
2760
2761         if (!drm_core_check_feature(dev, DRIVER_MODESET))
2762                 return -EINVAL;
2763
2764         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
2765
2766         obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
2767         if (!obj) {
2768                 ret = -EINVAL;
2769                 goto out;
2770         }
2771         connector = obj_to_connector(obj);
2772
2773         ret = drm_crtc_convert_umode(&mode, umode);
2774         if (ret) {
2775                 DRM_DEBUG_KMS("Invalid mode\n");
2776                 goto out;
2777         }
2778
2779         ret = drm_mode_detachmode(dev, connector, &mode);
2780 out:
2781         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
2782         return ret;
2783 }
2784
2785 struct drm_property *drm_property_create(struct drm_device *dev, int flags,
2786                                          const char *name, int num_values)
2787 {
2788         struct drm_property *property = NULL;
2789         int ret;
2790
2791         property = kmalloc(sizeof(struct drm_property), DRM_MEM_KMS,
2792             M_WAITOK | M_ZERO);
2793         if (!property)
2794                 return NULL;
2795
2796         if (num_values) {
2797                 property->values = kmalloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
2798                     M_WAITOK | M_ZERO);
2799                 if (!property->values)
2800                         goto fail;
2801         }
2802
2803         ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
2804         if (ret)
2805                 goto fail;
2806
2807         property->flags = flags;
2808         property->num_values = num_values;
2809         INIT_LIST_HEAD(&property->enum_blob_list);
2810
2811         if (name) {
2812                 strncpy(property->name, name, DRM_PROP_NAME_LEN);
2813                 property->name[DRM_PROP_NAME_LEN-1] = '\0';
2814         }
2815
2816         list_add_tail(&property->head, &dev->mode_config.property_list);
2817         return property;
2818 fail:
2819         drm_free(property->values, DRM_MEM_KMS);
2820         drm_free(property, DRM_MEM_KMS);
2821         return NULL;
2822 }
2823 EXPORT_SYMBOL(drm_property_create);
2824
2825 struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
2826                                          const char *name,
2827                                          const struct drm_prop_enum_list *props,
2828                                          int num_values)
2829 {
2830         struct drm_property *property;
2831         int i, ret;
2832
2833         flags |= DRM_MODE_PROP_ENUM;
2834
2835         property = drm_property_create(dev, flags, name, num_values);
2836         if (!property)
2837                 return NULL;
2838
2839         for (i = 0; i < num_values; i++) {
2840                 ret = drm_property_add_enum(property, i,
2841                                       props[i].type,
2842                                       props[i].name);
2843                 if (ret) {
2844                         drm_property_destroy(dev, property);
2845                         return NULL;
2846                 }
2847         }
2848
2849         return property;
2850 }
2851 EXPORT_SYMBOL(drm_property_create_enum);
2852
2853 struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
2854                                          int flags, const char *name,
2855                                          const struct drm_prop_enum_list *props,
2856                                          int num_values)
2857 {
2858         struct drm_property *property;
2859         int i, ret;
2860
2861         flags |= DRM_MODE_PROP_BITMASK;
2862
2863         property = drm_property_create(dev, flags, name, num_values);
2864         if (!property)
2865                 return NULL;
2866
2867         for (i = 0; i < num_values; i++) {
2868                 ret = drm_property_add_enum(property, i,
2869                                       props[i].type,
2870                                       props[i].name);
2871                 if (ret) {
2872                         drm_property_destroy(dev, property);
2873                         return NULL;
2874                 }
2875         }
2876
2877         return property;
2878 }
2879 EXPORT_SYMBOL(drm_property_create_bitmask);
2880
2881 struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
2882                                          const char *name,
2883                                          uint64_t min, uint64_t max)
2884 {
2885         struct drm_property *property;
2886
2887         flags |= DRM_MODE_PROP_RANGE;
2888
2889         property = drm_property_create(dev, flags, name, 2);
2890         if (!property)
2891                 return NULL;
2892
2893         property->values[0] = min;
2894         property->values[1] = max;
2895
2896         return property;
2897 }
2898 EXPORT_SYMBOL(drm_property_create_range);
2899
2900 int drm_property_add_enum(struct drm_property *property, int index,
2901                           uint64_t value, const char *name)
2902 {
2903         struct drm_property_enum *prop_enum;
2904
2905         if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
2906                 return -EINVAL;
2907
2908         /*
2909          * Bitmask enum properties have the additional constraint of values
2910          * from 0 to 63
2911          */
2912         if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
2913                 return -EINVAL;
2914
2915         if (!list_empty(&property->enum_blob_list)) {
2916                 list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
2917                         if (prop_enum->value == value) {
2918                                 strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2919                                 prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2920                                 return 0;
2921                         }
2922                 }
2923         }
2924
2925         prop_enum = kmalloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
2926             M_WAITOK | M_ZERO);
2927         if (!prop_enum)
2928                 return -ENOMEM;
2929
2930         strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
2931         prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
2932         prop_enum->value = value;
2933
2934         property->values[index] = value;
2935         list_add_tail(&prop_enum->head, &property->enum_blob_list);
2936         return 0;
2937 }
2938 EXPORT_SYMBOL(drm_property_add_enum);
2939
2940 void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
2941 {
2942         struct drm_property_enum *prop_enum, *pt;
2943
2944         list_for_each_entry_safe(prop_enum, pt, &property->enum_blob_list, head) {
2945                 list_del(&prop_enum->head);
2946                 drm_free(prop_enum, DRM_MEM_KMS);
2947         }
2948
2949         if (property->num_values)
2950                 drm_free(property->values, DRM_MEM_KMS);
2951         drm_mode_object_put(dev, &property->base);
2952         list_del(&property->head);
2953         drm_free(property, DRM_MEM_KMS);
2954 }
2955 EXPORT_SYMBOL(drm_property_destroy);
2956
2957 void drm_object_attach_property(struct drm_mode_object *obj,
2958                                 struct drm_property *property,
2959                                 uint64_t init_val)
2960 {
2961         int count = obj->properties->count;
2962
2963         if (count == DRM_OBJECT_MAX_PROPERTY) {
2964                 WARN(1, "Failed to attach object property (type: 0x%x). Please "
2965                         "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
2966                         "you see this message on the same object type.\n",
2967                         obj->type);
2968                 return;
2969         }
2970
2971         obj->properties->ids[count] = property->base.id;
2972         obj->properties->values[count] = init_val;
2973         obj->properties->count++;
2974 }
2975 EXPORT_SYMBOL(drm_object_attach_property);
2976
2977 int drm_object_property_set_value(struct drm_mode_object *obj,
2978                                   struct drm_property *property, uint64_t val)
2979 {
2980         int i;
2981
2982         for (i = 0; i < obj->properties->count; i++) {
2983                 if (obj->properties->ids[i] == property->base.id) {
2984                         obj->properties->values[i] = val;
2985                         return 0;
2986                 }
2987         }
2988
2989         return -EINVAL;
2990 }
2991 EXPORT_SYMBOL(drm_object_property_set_value);
2992
2993 int drm_object_property_get_value(struct drm_mode_object *obj,
2994                                   struct drm_property *property, uint64_t *val)
2995 {
2996         int i;
2997
2998         for (i = 0; i < obj->properties->count; i++) {
2999                 if (obj->properties->ids[i] == property->base.id) {
3000                         *val = obj->properties->values[i];
3001                         return 0;
3002                 }
3003         }
3004
3005         return -EINVAL;
3006 }
3007 EXPORT_SYMBOL(drm_object_property_get_value);
3008
3009 int drm_mode_getproperty_ioctl(struct drm_device *dev,
3010                                void *data, struct drm_file *file_priv)
3011 {
3012         struct drm_mode_object *obj;
3013         struct drm_mode_get_property *out_resp = data;
3014         struct drm_property *property;
3015         int enum_count = 0;
3016         int blob_count = 0;
3017         int value_count = 0;
3018         int ret = 0, i;
3019         int copied;
3020         struct drm_property_enum *prop_enum;
3021         struct drm_mode_property_enum __user *enum_ptr;
3022         struct drm_property_blob *prop_blob;
3023         uint32_t __user *blob_id_ptr;
3024         uint64_t __user *values_ptr;
3025         uint32_t __user *blob_length_ptr;
3026
3027         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3028                 return -EINVAL;
3029
3030         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3031         obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
3032         if (!obj) {
3033                 ret = -EINVAL;
3034                 goto done;
3035         }
3036         property = obj_to_property(obj);
3037
3038         if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
3039                 list_for_each_entry(prop_enum, &property->enum_blob_list, head)
3040                         enum_count++;
3041         } else if (property->flags & DRM_MODE_PROP_BLOB) {
3042                 list_for_each_entry(prop_blob, &property->enum_blob_list, head)
3043                         blob_count++;
3044         }
3045
3046         value_count = property->num_values;
3047
3048         strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
3049         out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
3050         out_resp->flags = property->flags;
3051
3052         if ((out_resp->count_values >= value_count) && value_count) {
3053                 values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
3054                 for (i = 0; i < value_count; i++) {
3055                         if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
3056                                 ret = -EFAULT;
3057                                 goto done;
3058                         }
3059                 }
3060         }
3061         out_resp->count_values = value_count;
3062
3063         if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
3064                 if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
3065                         copied = 0;
3066                         enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
3067                         list_for_each_entry(prop_enum, &property->enum_blob_list, head) {
3068
3069                                 if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
3070                                         ret = -EFAULT;
3071                                         goto done;
3072                                 }
3073
3074                                 if (copy_to_user(&enum_ptr[copied].name,
3075                                                  &prop_enum->name, DRM_PROP_NAME_LEN)) {
3076                                         ret = -EFAULT;
3077                                         goto done;
3078                                 }
3079                                 copied++;
3080                         }
3081                 }
3082                 out_resp->count_enum_blobs = enum_count;
3083         }
3084
3085         if (property->flags & DRM_MODE_PROP_BLOB) {
3086                 if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
3087                         copied = 0;
3088                         blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
3089                         blob_length_ptr = (uint32_t __user *)(unsigned long)out_resp->values_ptr;
3090
3091                         list_for_each_entry(prop_blob, &property->enum_blob_list, head) {
3092                                 if (put_user(prop_blob->base.id, blob_id_ptr + copied)) {
3093                                         ret = -EFAULT;
3094                                         goto done;
3095                                 }
3096
3097                                 if (put_user(prop_blob->length, blob_length_ptr + copied)) {
3098                                         ret = -EFAULT;
3099                                         goto done;
3100                                 }
3101
3102                                 copied++;
3103                         }
3104                 }
3105                 out_resp->count_enum_blobs = blob_count;
3106         }
3107 done:
3108         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3109         return ret;
3110 }
3111
3112 static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev, int length,
3113                                                           void *data)
3114 {
3115         struct drm_property_blob *blob;
3116         int ret;
3117
3118         if (!length || !data)
3119                 return NULL;
3120
3121         blob = kmalloc(sizeof(struct drm_property_blob) + length, DRM_MEM_KMS,
3122             M_WAITOK | M_ZERO);
3123         if (!blob)
3124                 return NULL;
3125
3126         ret = drm_mode_object_get(dev, &blob->base, DRM_MODE_OBJECT_BLOB);
3127         if (ret) {
3128                 drm_free(blob, DRM_MEM_KMS);
3129                 return NULL;
3130         }
3131
3132         blob->length = length;
3133
3134         memcpy(blob->data, data, length);
3135
3136         list_add_tail(&blob->head, &dev->mode_config.property_blob_list);
3137         return blob;
3138 }
3139
3140 static void drm_property_destroy_blob(struct drm_device *dev,
3141                                struct drm_property_blob *blob)
3142 {
3143         drm_mode_object_put(dev, &blob->base);
3144         list_del(&blob->head);
3145         drm_free(blob, DRM_MEM_KMS);
3146 }
3147
3148 int drm_mode_getblob_ioctl(struct drm_device *dev,
3149                            void *data, struct drm_file *file_priv)
3150 {
3151         struct drm_mode_object *obj;
3152         struct drm_mode_get_blob *out_resp = data;
3153         struct drm_property_blob *blob;
3154         int ret = 0;
3155         void __user *blob_ptr;
3156
3157         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3158                 return -EINVAL;
3159
3160         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3161         obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
3162         if (!obj) {
3163                 ret = -EINVAL;
3164                 goto done;
3165         }
3166         blob = obj_to_blob(obj);
3167
3168         if (out_resp->length == blob->length) {
3169                 blob_ptr = (void __user *)(unsigned long)out_resp->data;
3170                 if (copy_to_user(blob_ptr, blob->data, blob->length)){
3171                         ret = -EFAULT;
3172                         goto done;
3173                 }
3174         }
3175         out_resp->length = blob->length;
3176
3177 done:
3178         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3179         return ret;
3180 }
3181
3182 int drm_mode_connector_update_edid_property(struct drm_connector *connector,
3183                                             struct edid *edid)
3184 {
3185         struct drm_device *dev = connector->dev;
3186         int ret, size;
3187
3188         if (connector->edid_blob_ptr)
3189                 drm_property_destroy_blob(dev, connector->edid_blob_ptr);
3190
3191         /* Delete edid, when there is none. */
3192         if (!edid) {
3193                 connector->edid_blob_ptr = NULL;
3194                 ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
3195                 return ret;
3196         }
3197
3198         size = EDID_LENGTH * (1 + edid->extensions);
3199         connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
3200                                                             size, edid);
3201         if (!connector->edid_blob_ptr)
3202                 return -EINVAL;
3203
3204         ret = drm_object_property_set_value(&connector->base,
3205                                                dev->mode_config.edid_property,
3206                                                connector->edid_blob_ptr->base.id);
3207
3208         return ret;
3209 }
3210 EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
3211
3212 static bool drm_property_change_is_valid(struct drm_property *property,
3213                                          uint64_t value)
3214 {
3215         if (property->flags & DRM_MODE_PROP_IMMUTABLE)
3216                 return false;
3217         if (property->flags & DRM_MODE_PROP_RANGE) {
3218                 if (value < property->values[0] || value > property->values[1])
3219                         return false;
3220                 return true;
3221         } else if (property->flags & DRM_MODE_PROP_BITMASK) {
3222                 int i;
3223                 uint64_t valid_mask = 0;
3224                 for (i = 0; i < property->num_values; i++)
3225                         valid_mask |= (1ULL << property->values[i]);
3226                 return !(value & ~valid_mask);
3227         } else if (property->flags & DRM_MODE_PROP_BLOB) {
3228                 /* Only the driver knows */
3229                 return true;
3230         } else {
3231                 int i;
3232                 for (i = 0; i < property->num_values; i++)
3233                         if (property->values[i] == value)
3234                                 return true;
3235                 return false;
3236         }
3237 }
3238
3239 int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
3240                                        void *data, struct drm_file *file_priv)
3241 {
3242         struct drm_mode_connector_set_property *conn_set_prop = data;
3243         struct drm_mode_obj_set_property obj_set_prop = {
3244                 .value = conn_set_prop->value,
3245                 .prop_id = conn_set_prop->prop_id,
3246                 .obj_id = conn_set_prop->connector_id,
3247                 .obj_type = DRM_MODE_OBJECT_CONNECTOR
3248         };
3249
3250         /* It does all the locking and checking we need */
3251         return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
3252 }
3253
3254 static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
3255                                            struct drm_property *property,
3256                                            uint64_t value)
3257 {
3258         int ret = -EINVAL;
3259         struct drm_connector *connector = obj_to_connector(obj);
3260
3261         /* Do DPMS ourselves */
3262         if (property == connector->dev->mode_config.dpms_property) {
3263                 if (connector->funcs->dpms)
3264                         (*connector->funcs->dpms)(connector, (int)value);
3265                 ret = 0;
3266         } else if (connector->funcs->set_property)
3267                 ret = connector->funcs->set_property(connector, property, value);
3268
3269         /* store the property value if successful */
3270         if (!ret)
3271                 drm_object_property_set_value(&connector->base, property, value);
3272         return ret;
3273 }
3274
3275 static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
3276                                       struct drm_property *property,
3277                                       uint64_t value)
3278 {
3279         int ret = -EINVAL;
3280         struct drm_crtc *crtc = obj_to_crtc(obj);
3281
3282         if (crtc->funcs->set_property)
3283                 ret = crtc->funcs->set_property(crtc, property, value);
3284         if (!ret)
3285                 drm_object_property_set_value(obj, property, value);
3286
3287         return ret;
3288 }
3289
3290 static int drm_mode_plane_set_obj_prop(struct drm_mode_object *obj,
3291                                       struct drm_property *property,
3292                                       uint64_t value)
3293 {
3294         int ret = -EINVAL;
3295         struct drm_plane *plane = obj_to_plane(obj);
3296
3297         if (plane->funcs->set_property)
3298                 ret = plane->funcs->set_property(plane, property, value);
3299         if (!ret)
3300                 drm_object_property_set_value(obj, property, value);
3301
3302         return ret;
3303 }
3304
3305 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
3306                                       struct drm_file *file_priv)
3307 {
3308         struct drm_mode_obj_get_properties *arg = data;
3309         struct drm_mode_object *obj;
3310         int ret = 0;
3311         int i;
3312         int copied = 0;
3313         int props_count = 0;
3314         uint32_t __user *props_ptr;
3315         uint64_t __user *prop_values_ptr;
3316
3317         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3318                 return -EINVAL;
3319
3320         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3321
3322         obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3323         if (!obj) {
3324                 ret = -EINVAL;
3325                 goto out;
3326         }
3327         if (!obj->properties) {
3328                 ret = -EINVAL;
3329                 goto out;
3330         }
3331
3332         props_count = obj->properties->count;
3333
3334         /* This ioctl is called twice, once to determine how much space is
3335          * needed, and the 2nd time to fill it. */
3336         if ((arg->count_props >= props_count) && props_count) {
3337                 copied = 0;
3338                 props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr);
3339                 prop_values_ptr = (uint64_t __user *)(unsigned long)
3340                                   (arg->prop_values_ptr);
3341                 for (i = 0; i < props_count; i++) {
3342                         if (put_user(obj->properties->ids[i],
3343                                      props_ptr + copied)) {
3344                                 ret = -EFAULT;
3345                                 goto out;
3346                         }
3347                         if (put_user(obj->properties->values[i],
3348                                      prop_values_ptr + copied)) {
3349                                 ret = -EFAULT;
3350                                 goto out;
3351                         }
3352                         copied++;
3353                 }
3354         }
3355         arg->count_props = props_count;
3356 out:
3357         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3358         return ret;
3359 }
3360
3361 int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
3362                                     struct drm_file *file_priv)
3363 {
3364         struct drm_mode_obj_set_property *arg = data;
3365         struct drm_mode_object *arg_obj;
3366         struct drm_mode_object *prop_obj;
3367         struct drm_property *property;
3368         int ret = -EINVAL;
3369         int i;
3370
3371         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3372                 return -EINVAL;
3373
3374         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3375
3376         arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
3377         if (!arg_obj)
3378                 goto out;
3379         if (!arg_obj->properties)
3380                 goto out;
3381
3382         for (i = 0; i < arg_obj->properties->count; i++)
3383                 if (arg_obj->properties->ids[i] == arg->prop_id)
3384                         break;
3385
3386         if (i == arg_obj->properties->count)
3387                 goto out;
3388
3389         prop_obj = drm_mode_object_find(dev, arg->prop_id,
3390                                         DRM_MODE_OBJECT_PROPERTY);
3391         if (!prop_obj)
3392                 goto out;
3393         property = obj_to_property(prop_obj);
3394
3395         if (!drm_property_change_is_valid(property, arg->value))
3396                 goto out;
3397
3398         switch (arg_obj->type) {
3399         case DRM_MODE_OBJECT_CONNECTOR:
3400                 ret = drm_mode_connector_set_obj_prop(arg_obj, property,
3401                                                       arg->value);
3402                 break;
3403         case DRM_MODE_OBJECT_CRTC:
3404                 ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
3405                 break;
3406         case DRM_MODE_OBJECT_PLANE:
3407                 ret = drm_mode_plane_set_obj_prop(arg_obj, property, arg->value);
3408                 break;
3409         }
3410
3411 out:
3412         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3413         return ret;
3414 }
3415
3416 int drm_mode_connector_attach_encoder(struct drm_connector *connector,
3417                                       struct drm_encoder *encoder)
3418 {
3419         int i;
3420
3421         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3422                 if (connector->encoder_ids[i] == 0) {
3423                         connector->encoder_ids[i] = encoder->base.id;
3424                         return 0;
3425                 }
3426         }
3427         return -ENOMEM;
3428 }
3429 EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
3430
3431 void drm_mode_connector_detach_encoder(struct drm_connector *connector,
3432                                     struct drm_encoder *encoder)
3433 {
3434         int i;
3435         for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
3436                 if (connector->encoder_ids[i] == encoder->base.id) {
3437                         connector->encoder_ids[i] = 0;
3438                         if (connector->encoder == encoder)
3439                                 connector->encoder = NULL;
3440                         break;
3441                 }
3442         }
3443 }
3444 EXPORT_SYMBOL(drm_mode_connector_detach_encoder);
3445
3446 int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
3447                                   int gamma_size)
3448 {
3449         crtc->gamma_size = gamma_size;
3450
3451         crtc->gamma_store = kmalloc(gamma_size * sizeof(uint16_t) * 3,
3452             DRM_MEM_KMS, M_WAITOK | M_ZERO);
3453         if (!crtc->gamma_store) {
3454                 crtc->gamma_size = 0;
3455                 return -ENOMEM;
3456         }
3457
3458         return 0;
3459 }
3460 EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
3461
3462 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
3463                              void *data, struct drm_file *file_priv)
3464 {
3465         struct drm_mode_crtc_lut *crtc_lut = data;
3466         struct drm_mode_object *obj;
3467         struct drm_crtc *crtc;
3468         void *r_base, *g_base, *b_base;
3469         int size;
3470         int ret = 0;
3471
3472         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3473                 return -EINVAL;
3474
3475         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3476         obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3477         if (!obj) {
3478                 ret = -EINVAL;
3479                 goto out;
3480         }
3481         crtc = obj_to_crtc(obj);
3482
3483         if (crtc->funcs->gamma_set == NULL) {
3484                 ret = -ENOSYS;
3485                 goto out;
3486         }
3487
3488         /* memcpy into gamma store */
3489         if (crtc_lut->gamma_size != crtc->gamma_size) {
3490                 ret = -EINVAL;
3491                 goto out;
3492         }
3493
3494         size = crtc_lut->gamma_size * (sizeof(uint16_t));
3495         r_base = crtc->gamma_store;
3496         if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
3497                 ret = -EFAULT;
3498                 goto out;
3499         }
3500
3501         g_base = (char *)r_base + size;
3502         if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
3503                 ret = -EFAULT;
3504                 goto out;
3505         }
3506
3507         b_base = (char *)g_base + size;
3508         if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
3509                 ret = -EFAULT;
3510                 goto out;
3511         }
3512
3513         crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size);
3514
3515 out:
3516         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3517         return ret;
3518
3519 }
3520
3521 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
3522                              void *data, struct drm_file *file_priv)
3523 {
3524         struct drm_mode_crtc_lut *crtc_lut = data;
3525         struct drm_mode_object *obj;
3526         struct drm_crtc *crtc;
3527         void *r_base, *g_base, *b_base;
3528         int size;
3529         int ret = 0;
3530
3531         if (!drm_core_check_feature(dev, DRIVER_MODESET))
3532                 return -EINVAL;
3533
3534         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3535         obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
3536         if (!obj) {
3537                 ret = -EINVAL;
3538                 goto out;
3539         }
3540         crtc = obj_to_crtc(obj);
3541
3542         /* memcpy into gamma store */
3543         if (crtc_lut->gamma_size != crtc->gamma_size) {
3544                 ret = -EINVAL;
3545                 goto out;
3546         }
3547
3548         size = crtc_lut->gamma_size * (sizeof(uint16_t));
3549         r_base = crtc->gamma_store;
3550         if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
3551                 ret = -EFAULT;
3552                 goto out;
3553         }
3554
3555         g_base = (char *)r_base + size;
3556         if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
3557                 ret = -EFAULT;
3558                 goto out;
3559         }
3560
3561         b_base = (char *)g_base + size;
3562         if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
3563                 ret = -EFAULT;
3564                 goto out;
3565         }
3566 out:
3567         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3568         return ret;
3569 }
3570
3571 static void
3572 drm_kms_free(void *arg)
3573 {
3574
3575         drm_free(arg, DRM_MEM_KMS);
3576 }
3577
3578 int drm_mode_page_flip_ioctl(struct drm_device *dev,
3579                              void *data, struct drm_file *file_priv)
3580 {
3581         struct drm_mode_crtc_page_flip *page_flip = data;
3582         struct drm_mode_object *obj;
3583         struct drm_crtc *crtc;
3584         struct drm_framebuffer *fb;
3585         struct drm_pending_vblank_event *e = NULL;
3586         int hdisplay, vdisplay;
3587         int ret = -EINVAL;
3588
3589         if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
3590             page_flip->reserved != 0)
3591                 return -EINVAL;
3592
3593         lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
3594         obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
3595         if (!obj)
3596                 goto out;
3597         crtc = obj_to_crtc(obj);
3598
3599         if (crtc->fb == NULL) {
3600                 /* The framebuffer is currently unbound, presumably
3601                  * due to a hotplug event, that userspace has not
3602                  * yet discovered.
3603                  */
3604                 ret = -EBUSY;
3605                 goto out;
3606         }
3607
3608         if (crtc->funcs->page_flip == NULL)
3609                 goto out;
3610
3611         obj = drm_mode_object_find(dev, page_flip->fb_id, DRM_MODE_OBJECT_FB);
3612         if (!obj)
3613                 goto out;
3614         fb = obj_to_fb(obj);
3615
3616         hdisplay = crtc->mode.hdisplay;
3617         vdisplay = crtc->mode.vdisplay;
3618
3619         if (crtc->invert_dimensions)
3620                 swap(hdisplay, vdisplay);
3621
3622         if (hdisplay > fb->width ||
3623             vdisplay > fb->height ||
3624             crtc->x > fb->width - hdisplay ||
3625             crtc->y > fb->height - vdisplay) {
3626                 DRM_DEBUG_KMS("Invalid fb size %ux%u for CRTC viewport %ux%u+%d+%d%s.\n",
3627                               fb->width, fb->height, hdisplay, vdisplay, crtc->x, crtc->y,
3628                               crtc->invert_dimensions ? " (inverted)" : "");
3629                 ret = -ENOSPC;
3630                 goto out;
3631         }
3632
3633         if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3634                 ret = -ENOMEM;
3635                 lockmgr(&dev->event_lock, LK_EXCLUSIVE);
3636                 if (file_priv->event_space < sizeof e->event) {
3637                         lockmgr(&dev->event_lock, LK_RELEASE);
3638                         goto out;
3639                 }
3640                 file_priv->event_space -= sizeof e->event;
3641                 lockmgr(&dev->event_lock, LK_RELEASE);
3642
3643                 e = kmalloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
3644                 if (e == NULL) {
3645                         lockmgr(&dev->event_lock, LK_EXCLUSIVE);
3646                         file_priv->event_space += sizeof e->event;
3647                         lockmgr(&dev->event_lock, LK_RELEASE);
3648                         goto out;
3649                 }
3650
3651                 e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
3652                 e->event.base.length = sizeof e->event;
3653                 e->event.user_data = page_flip->user_data;
3654                 e->base.event = &e->event.base;
3655                 e->base.file_priv = file_priv;
3656                 e->base.destroy =
3657                         (void (*) (struct drm_pending_event *))drm_kms_free;
3658         }
3659
3660         ret = crtc->funcs->page_flip(crtc, fb, e);
3661         if (ret) {
3662                 if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
3663                         lockmgr(&dev->event_lock, LK_EXCLUSIVE);
3664                         file_priv->event_space += sizeof e->event;
3665                         lockmgr(&dev->event_lock, LK_RELEASE);
3666                         drm_free(e, DRM_MEM_KMS);
3667                 }
3668         }
3669
3670 out:
3671         lockmgr(&dev->mode_config.mutex, LK_RELEASE);
3672         return ret;
3673 }
3674
3675 void drm_mode_config_reset(struct drm_device *dev)
3676 {
3677         struct drm_crtc *crtc;
3678         struct drm_encoder *encoder;
3679         struct drm_connector *connector;
3680
3681         list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
3682                 if (crtc->funcs->reset)
3683                         crtc->funcs->reset(crtc);
3684
3685         list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
3686                 if (encoder->funcs->reset)
3687                         encoder->funcs->reset(encoder);
3688
3689         list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
3690                 connector->status = connector_status_unknown;
3691
3692                 if (connector->funcs->reset)
3693                         connector->funcs->reset(connector);
3694         }
3695 }
3696 EXPORT_SYMBOL(drm_mode_config_reset);
3697
3698 int drm_mode_create_dumb_ioctl(struct drm_device *dev,
3699                                void *data, struct drm_file *file_priv)
3700 {
3701         struct drm_mode_create_dumb *args = data;
3702
3703         if (!dev->driver->dumb_create)
3704                 return -ENOSYS;
3705         return dev->driver->dumb_create(file_priv, dev, args);
3706 }
3707
3708 int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
3709                              void *data, struct drm_file *file_priv)
3710 {
3711         struct drm_mode_map_dumb *args = data;
3712
3713         /* call driver ioctl to get mmap offset */
3714         if (!dev->driver->dumb_map_offset)
3715                 return -ENOSYS;
3716
3717         return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
3718 }
3719
3720 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
3721                                 void *data, struct drm_file *file_priv)
3722 {
3723         struct drm_mode_destroy_dumb *args = data;
3724
3725         if (!dev->driver->dumb_destroy)
3726                 return -ENOSYS;
3727
3728         return dev->driver->dumb_destroy(file_priv, dev, args->handle);
3729 }
3730
3731 /*
3732  * Just need to support RGB formats here for compat with code that doesn't
3733  * use pixel formats directly yet.
3734  */
3735 void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth,
3736                           int *bpp)
3737 {
3738         switch (format) {
3739         case DRM_FORMAT_RGB332:
3740         case DRM_FORMAT_BGR233:
3741                 *depth = 8;
3742                 *bpp = 8;
3743                 break;
3744         case DRM_FORMAT_XRGB1555:
3745         case DRM_FORMAT_XBGR1555:
3746         case DRM_FORMAT_RGBX5551:
3747         case DRM_FORMAT_BGRX5551:
3748         case DRM_FORMAT_ARGB1555:
3749         case DRM_FORMAT_ABGR1555:
3750         case DRM_FORMAT_RGBA5551:
3751         case DRM_FORMAT_BGRA5551:
3752                 *depth = 15;
3753                 *bpp = 16;
3754                 break;
3755         case DRM_FORMAT_RGB565:
3756         case DRM_FORMAT_BGR565:
3757                 *depth = 16;
3758                 *bpp = 16;
3759                 break;
3760         case DRM_FORMAT_RGB888:
3761         case DRM_FORMAT_BGR888:
3762                 *depth = 24;
3763                 *bpp = 24;
3764                 break;
3765         case DRM_FORMAT_XRGB8888:
3766         case DRM_FORMAT_XBGR8888:
3767         case DRM_FORMAT_RGBX8888:
3768         case DRM_FORMAT_BGRX8888:
3769                 *depth = 24;
3770                 *bpp = 32;
3771                 break;
3772         case DRM_FORMAT_XRGB2101010:
3773         case DRM_FORMAT_XBGR2101010:
3774         case DRM_FORMAT_RGBX1010102:
3775         case DRM_FORMAT_BGRX1010102:
3776         case DRM_FORMAT_ARGB2101010:
3777         case DRM_FORMAT_ABGR2101010:
3778         case DRM_FORMAT_RGBA1010102:
3779         case DRM_FORMAT_BGRA1010102:
3780                 *depth = 30;
3781                 *bpp = 32;
3782                 break;
3783         case DRM_FORMAT_ARGB8888:
3784         case DRM_FORMAT_ABGR8888:
3785         case DRM_FORMAT_RGBA8888:
3786         case DRM_FORMAT_BGRA8888:
3787                 *depth = 32;
3788                 *bpp = 32;
3789                 break;
3790         default:
3791                 DRM_DEBUG_KMS("unsupported pixel format\n");
3792                 *depth = 0;
3793                 *bpp = 0;
3794                 break;
3795         }
3796 }
3797 EXPORT_SYMBOL(drm_fb_get_bpp_depth);
3798
3799 /**
3800  * drm_format_num_planes - get the number of planes for format
3801  * @format: pixel format (DRM_FORMAT_*)
3802  *
3803  * RETURNS:
3804  * The number of planes used by the specified pixel format.
3805  */
3806 int drm_format_num_planes(uint32_t format)
3807 {
3808         switch (format) {
3809         case DRM_FORMAT_YUV410:
3810         case DRM_FORMAT_YVU410:
3811         case DRM_FORMAT_YUV411:
3812         case DRM_FORMAT_YVU411:
3813         case DRM_FORMAT_YUV420:
3814         case DRM_FORMAT_YVU420:
3815         case DRM_FORMAT_YUV422:
3816         case DRM_FORMAT_YVU422:
3817         case DRM_FORMAT_YUV444:
3818         case DRM_FORMAT_YVU444:
3819                 return 3;
3820         case DRM_FORMAT_NV12:
3821         case DRM_FORMAT_NV21:
3822         case DRM_FORMAT_NV16:
3823         case DRM_FORMAT_NV61:
3824         case DRM_FORMAT_NV24:
3825         case DRM_FORMAT_NV42:
3826                 return 2;
3827         default:
3828                 return 1;
3829         }
3830 }
3831 EXPORT_SYMBOL(drm_format_num_planes);
3832
3833 /**
3834  * drm_format_plane_cpp - determine the bytes per pixel value
3835  * @format: pixel format (DRM_FORMAT_*)
3836  * @plane: plane index
3837  *
3838  * RETURNS:
3839  * The bytes per pixel value for the specified plane.
3840  */
3841 int drm_format_plane_cpp(uint32_t format, int plane)
3842 {
3843         unsigned int depth;
3844         int bpp;
3845
3846         if (plane >= drm_format_num_planes(format))
3847                 return 0;
3848
3849         switch (format) {
3850         case DRM_FORMAT_YUYV:
3851         case DRM_FORMAT_YVYU:
3852         case DRM_FORMAT_UYVY:
3853         case DRM_FORMAT_VYUY:
3854                 return 2;
3855         case DRM_FORMAT_NV12:
3856         case DRM_FORMAT_NV21:
3857         case DRM_FORMAT_NV16:
3858         case DRM_FORMAT_NV61:
3859         case DRM_FORMAT_NV24:
3860         case DRM_FORMAT_NV42:
3861                 return plane ? 2 : 1;
3862         case DRM_FORMAT_YUV410:
3863         case DRM_FORMAT_YVU410:
3864         case DRM_FORMAT_YUV411:
3865         case DRM_FORMAT_YVU411:
3866         case DRM_FORMAT_YUV420:
3867         case DRM_FORMAT_YVU420:
3868         case DRM_FORMAT_YUV422:
3869         case DRM_FORMAT_YVU422:
3870         case DRM_FORMAT_YUV444:
3871         case DRM_FORMAT_YVU444:
3872                 return 1;
3873         default:
3874                 drm_fb_get_bpp_depth(format, &depth, &bpp);
3875                 return bpp >> 3;
3876         }
3877 }
3878 EXPORT_SYMBOL(drm_format_plane_cpp);
3879
3880 /**
3881  * drm_format_horz_chroma_subsampling - get the horizontal chroma subsampling factor
3882  * @format: pixel format (DRM_FORMAT_*)
3883  *
3884  * RETURNS:
3885  * The horizontal chroma subsampling factor for the
3886  * specified pixel format.
3887  */
3888 int drm_format_horz_chroma_subsampling(uint32_t format)
3889 {
3890         switch (format) {
3891         case DRM_FORMAT_YUV411:
3892         case DRM_FORMAT_YVU411:
3893         case DRM_FORMAT_YUV410:
3894         case DRM_FORMAT_YVU410:
3895                 return 4;
3896         case DRM_FORMAT_YUYV:
3897         case DRM_FORMAT_YVYU:
3898         case DRM_FORMAT_UYVY:
3899         case DRM_FORMAT_VYUY:
3900         case DRM_FORMAT_NV12:
3901         case DRM_FORMAT_NV21:
3902         case DRM_FORMAT_NV16:
3903         case DRM_FORMAT_NV61:
3904         case DRM_FORMAT_YUV422:
3905         case DRM_FORMAT_YVU422:
3906         case DRM_FORMAT_YUV420:
3907         case DRM_FORMAT_YVU420:
3908                 return 2;
3909         default:
3910                 return 1;
3911         }
3912 }
3913 EXPORT_SYMBOL(drm_format_horz_chroma_subsampling);
3914
3915 /**
3916  * drm_format_vert_chroma_subsampling - get the vertical chroma subsampling factor
3917  * @format: pixel format (DRM_FORMAT_*)
3918  *
3919  * RETURNS:
3920  * The vertical chroma subsampling factor for the
3921  * specified pixel format.
3922  */
3923 int drm_format_vert_chroma_subsampling(uint32_t format)
3924 {
3925         switch (format) {
3926         case DRM_FORMAT_YUV410:
3927         case DRM_FORMAT_YVU410:
3928                 return 4;
3929         case DRM_FORMAT_YUV420:
3930         case DRM_FORMAT_YVU420:
3931         case DRM_FORMAT_NV12:
3932         case DRM_FORMAT_NV21:
3933                 return 2;
3934         default:
3935                 return 1;
3936         }
3937 }
3938 EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);