The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/drm2/drm_crtc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 113080214ae3d7d355fd855bf8f1f8d5


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.