All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Paul <seanpaul@chromium.org>
To: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Daniel Vetter <daniel.vetter@intel.com>,
	Intel Graphics Development <intel-gfx@lists.freedesktop.org>,
	DRI Development <dri-devel@lists.freedesktop.org>
Subject: Re: [PATCH 14/20] drm: Extract drm_connector.[hc]
Date: Wed, 10 Aug 2016 11:06:07 -0400	[thread overview]
Message-ID: <CAOw6vbJv6D9o9beaiy-P_JvRa6GGAVLNgfG+8Dd26y3Ba-rwRQ@mail.gmail.com> (raw)
In-Reply-To: <1470750091-16627-15-git-send-email-daniel.vetter@ffwll.ch>

On Tue, Aug 9, 2016 at 9:41 AM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Pulls in quite a lot of connector related structures (cmdline mode,
> force/status enums, display info), but I think that all makes perfect
> sense.
>
> Also had to move a few more core kms object stuff into drm_modeset.h.
>
> And as a first cleanup remove the kerneldoc for the 2 connector IOCTL
> - DRM core docs are aimed at drivers, no point documenting internal in
> excruciating detail.
>
> v2: And also pull in all the connector property code.
>

\o/

I picked a few nits below, but nothing functional and nothing that
wasn't already existing in drm_crtc.c. I twitched at a few other
really small things while I was reading, so I'll post a follow-on
cleanup patch for drm_connector. Feel free to disregard my nits below
and I'll scoop them up later.

Sean

> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  Documentation/gpu/drm-kms.rst       |    9 +
>  drivers/gpu/drm/Makefile            |    2 +-
>  drivers/gpu/drm/drm_connector.c     | 1058 +++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_crtc.c          | 1110 +----------------------------------
>  drivers/gpu/drm/drm_crtc_internal.h |   26 +-
>  include/drm/drm_connector.h         |  644 ++++++++++++++++++++
>  include/drm/drm_crtc.h              |  601 +------------------
>  include/drm/drm_modes.h             |   16 +-
>  include/drm/drm_modeset.h           |   36 +-
>  9 files changed, 1773 insertions(+), 1729 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_connector.c
>  create mode 100644 include/drm/drm_connector.h
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index d244e03658cc..449acc2517c7 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -110,6 +110,15 @@ Display Modes Function Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_modes.c
>     :export:
>
> +Connector Display Sink Abstraction
> +==================================
> +
> +.. kernel-doc:: include/drm/drm_connector.h
> +   :internal:
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_connector.c
> +   :export:
> +
>  KMS Initialization and Cleanup
>  ==============================
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index c71ec42ce511..2eff1a33ab63 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -13,7 +13,7 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
>                 drm_trace_points.o drm_global.o drm_prime.o \
>                 drm_rect.o drm_vma_manager.o drm_flip_work.o \
>                 drm_modeset_lock.o drm_atomic.o drm_bridge.o \
> -               drm_framebuffer.o
> +               drm_framebuffer.o drm_connector.o
>
>  drm-$(CONFIG_COMPAT) += drm_ioc32.o
>  drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> new file mode 100644
> index 000000000000..99ece6758061
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -0,0 +1,1058 @@
> +/*
> + * Copyright (c) 2016 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_connector.h>
> +#include <drm/drm_edid.h>
> +
> +#include "drm_crtc_internal.h"
> +#include "drm_internal.h"
> +
> +struct drm_conn_prop_enum_list {
> +       int type;
> +       const char *name;
> +       struct ida ida;
> +};
> +
> +/*
> + * Connector and encoder types.
> + */
> +static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
> +       { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
> +       { DRM_MODE_CONNECTOR_VGA, "VGA" },
> +       { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
> +       { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
> +       { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
> +       { DRM_MODE_CONNECTOR_Composite, "Composite" },
> +       { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
> +       { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
> +       { DRM_MODE_CONNECTOR_Component, "Component" },
> +       { DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
> +       { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
> +       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
> +       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
> +       { DRM_MODE_CONNECTOR_TV, "TV" },
> +       { DRM_MODE_CONNECTOR_eDP, "eDP" },
> +       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
> +       { DRM_MODE_CONNECTOR_DSI, "DSI" },
> +       { DRM_MODE_CONNECTOR_DPI, "DPI" },
> +};
> +
> +void drm_connector_ida_init(void)
> +{
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
> +               ida_init(&drm_connector_enum_list[i].ida);
> +}
> +
> +void drm_connector_ida_destroy(void)
> +{
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
> +               ida_destroy(&drm_connector_enum_list[i].ida);
> +}
> +
> +/**
> + * drm_connector_get_cmdline_mode - reads the user's cmdline mode
> + * @connector: connector to quwery
> + *
> + * The kernel supports per-connector configration of its consoles through

While we're here, s/configration/configuration/


> + * use of the video= parameter. This function parses that option and
> + * extracts the user's specified mode (or enable/disable status) for a
> + * particular connector. This is typically only used during the early fbdev
> + * setup.
> + */
> +static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
> +{
> +       struct drm_cmdline_mode *mode = &connector->cmdline_mode;
> +       char *option = NULL;
> +
> +       if (fb_get_options(connector->name, &option))
> +               return;
> +
> +       if (!drm_mode_parse_command_line_for_connector(option,
> +                                                      connector,
> +                                                      mode))
> +               return;
> +
> +       if (mode->force) {
> +               const char *s;
> +
> +               switch (mode->force) {
> +               case DRM_FORCE_OFF:
> +                       s = "OFF";
> +                       break;
> +               case DRM_FORCE_ON_DIGITAL:
> +                       s = "ON - dig";
> +                       break;
> +               default:
> +               case DRM_FORCE_ON:
> +                       s = "ON";
> +                       break;
> +               }
> +
> +               DRM_INFO("forcing %s connector %s\n", connector->name, s);
> +               connector->force = mode->force;
> +       }
> +
> +       DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
> +                     connector->name,
> +                     mode->xres, mode->yres,
> +                     mode->refresh_specified ? mode->refresh : 60,
> +                     mode->rb ? " reduced blanking" : "",
> +                     mode->margins ? " with margins" : "",
> +                     mode->interlace ?  " interlaced" : "");
> +}
> +
> +static void drm_connector_free(struct kref *kref)
> +{
> +       struct drm_connector *connector =
> +               container_of(kref, struct drm_connector, base.refcount);
> +       struct drm_device *dev = connector->dev;
> +
> +       drm_mode_object_unregister(dev, &connector->base);
> +       connector->funcs->destroy(connector);
> +}
> +
> +/**
> + * drm_connector_init - Init a preallocated connector
> + * @dev: DRM device
> + * @connector: the connector to init
> + * @funcs: callbacks for this connector
> + * @connector_type: user visible type of the connector
> + *
> + * Initialises a preallocated connector. Connectors should be
> + * subclassed as part of driver connector objects.
> + *
> + * Returns:
> + * Zero on success, error code on failure.
> + */
> +int drm_connector_init(struct drm_device *dev,
> +                      struct drm_connector *connector,
> +                      const struct drm_connector_funcs *funcs,
> +                      int connector_type)
> +{
> +       struct drm_mode_config *config = &dev->mode_config;
> +       int ret;
> +       struct ida *connector_ida =
> +               &drm_connector_enum_list[connector_type].ida;
> +
> +       drm_modeset_lock_all(dev);
> +
> +       ret = drm_mode_object_get_reg(dev, &connector->base,
> +                                     DRM_MODE_OBJECT_CONNECTOR,
> +                                     false, drm_connector_free);
> +       if (ret)
> +               goto out_unlock;
> +
> +       connector->base.properties = &connector->properties;
> +       connector->dev = dev;
> +       connector->funcs = funcs;
> +
> +       ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
> +       if (ret < 0)
> +               goto out_put;
> +       connector->index = ret;
> +       ret = 0;
> +
> +       connector->connector_type = connector_type;
> +       connector->connector_type_id =
> +               ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
> +       if (connector->connector_type_id < 0) {
> +               ret = connector->connector_type_id;
> +               goto out_put_id;
> +       }
> +       connector->name =
> +               kasprintf(GFP_KERNEL, "%s-%d",
> +                         drm_connector_enum_list[connector_type].name,
> +                         connector->connector_type_id);
> +       if (!connector->name) {
> +               ret = -ENOMEM;
> +               goto out_put_type_id;
> +       }
> +
> +       INIT_LIST_HEAD(&connector->probed_modes);
> +       INIT_LIST_HEAD(&connector->modes);
> +       connector->edid_blob_ptr = NULL;
> +       connector->status = connector_status_unknown;
> +
> +       drm_connector_get_cmdline_mode(connector);
> +
> +       /* We should add connectors at the end to avoid upsetting the connector
> +        * index too much. */
> +       list_add_tail(&connector->head, &config->connector_list);
> +       config->num_connector++;
> +
> +       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> +               drm_object_attach_property(&connector->base,
> +                                             config->edid_property,
> +                                             0);
> +
> +       drm_object_attach_property(&connector->base,
> +                                     config->dpms_property, 0);
> +
> +       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
> +               drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
> +       }
> +
> +       connector->debugfs_entry = NULL;
> +out_put_type_id:
> +       if (ret)
> +               ida_remove(connector_ida, connector->connector_type_id);
> +out_put_id:
> +       if (ret)
> +               ida_remove(&config->connector_ida, connector->index);
> +out_put:
> +       if (ret)
> +               drm_mode_object_unregister(dev, &connector->base);
> +
> +out_unlock:
> +       drm_modeset_unlock_all(dev);
> +
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_connector_init);
> +
> +/**
> + * drm_mode_connector_attach_encoder - attach a connector to an encoder
> + * @connector: connector to attach
> + * @encoder: encoder to attach @connector to
> + *
> + * This function links up a connector to an encoder. Note that the routing
> + * restrictions between encoders and crtcs are exposed to userspace through the
> + * possible_clones and possible_crtcs bitmasks.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_connector_attach_encoder(struct drm_connector *connector,
> +                                     struct drm_encoder *encoder)
> +{
> +       int i;
> +
> +       /*
> +        * In the past, drivers have attempted to model the static association
> +        * of connector to encoder in simple connector/encoder devices using a
> +        * direct assignment of connector->encoder = encoder. This connection
> +        * is a logical one and the responsibility of the core, so drivers are
> +        * expected not to mess with this.
> +        *
> +        * Note that the error return should've been enough here, but a large
> +        * majority of drivers ignores the return value, so add in a big WARN
> +        * to get people's attention.
> +        */
> +       if (WARN_ON(connector->encoder))
> +               return -EINVAL;
> +
> +       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> +               if (connector->encoder_ids[i] == 0) {
> +                       connector->encoder_ids[i] = encoder->base.id;
> +                       return 0;
> +               }
> +       }
> +       return -ENOMEM;
> +}
> +EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
> +
> +static void drm_mode_remove(struct drm_connector *connector,
> +                           struct drm_display_mode *mode)
> +{
> +       list_del(&mode->head);
> +       drm_mode_destroy(connector->dev, mode);
> +}
> +
> +/**
> + * drm_connector_cleanup - cleans up an initialised connector
> + * @connector: connector to cleanup
> + *
> + * Cleans up the connector but doesn't free the object.
> + */
> +void drm_connector_cleanup(struct drm_connector *connector)
> +{
> +       struct drm_device *dev = connector->dev;
> +       struct drm_display_mode *mode, *t;
> +
> +       /* The connector should have been removed from userspace long before
> +        * it is finally destroyed.
> +        */
> +       if (WARN_ON(connector->registered))
> +               drm_connector_unregister(connector);
> +
> +       if (connector->tile_group) {
> +               drm_mode_put_tile_group(dev, connector->tile_group);
> +               connector->tile_group = NULL;
> +       }
> +
> +       list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
> +               drm_mode_remove(connector, mode);
> +
> +       list_for_each_entry_safe(mode, t, &connector->modes, head)
> +               drm_mode_remove(connector, mode);
> +
> +       ida_remove(&drm_connector_enum_list[connector->connector_type].ida,
> +                  connector->connector_type_id);
> +
> +       ida_remove(&dev->mode_config.connector_ida,
> +                  connector->index);
> +
> +       kfree(connector->display_info.bus_formats);
> +       drm_mode_object_unregister(dev, &connector->base);
> +       kfree(connector->name);
> +       connector->name = NULL;
> +       list_del(&connector->head);
> +       dev->mode_config.num_connector--;
> +
> +       WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
> +       if (connector->state && connector->funcs->atomic_destroy_state)
> +               connector->funcs->atomic_destroy_state(connector,
> +                                                      connector->state);
> +
> +       memset(connector, 0, sizeof(*connector));
> +}
> +EXPORT_SYMBOL(drm_connector_cleanup);
> +
> +/**
> + * drm_connector_register - register a connector
> + * @connector: the connector to register
> + *
> + * Register userspace interfaces for a connector
> + *
> + * Returns:
> + * Zero on success, error code on failure.
> + */
> +int drm_connector_register(struct drm_connector *connector)
> +{
> +       int ret;
> +
> +       if (connector->registered)
> +               return 0;
> +
> +       ret = drm_sysfs_connector_add(connector);
> +       if (ret)
> +               return ret;
> +
> +       ret = drm_debugfs_connector_add(connector);
> +       if (ret) {
> +               goto err_sysfs;
> +       }

clean up the braces here, too?

> +
> +       if (connector->funcs->late_register) {
> +               ret = connector->funcs->late_register(connector);
> +               if (ret)
> +                       goto err_debugfs;
> +       }
> +
> +       drm_mode_object_register(connector->dev, &connector->base);
> +
> +       connector->registered = true;
> +       return 0;
> +
> +err_debugfs:
> +       drm_debugfs_connector_remove(connector);
> +err_sysfs:
> +       drm_sysfs_connector_remove(connector);
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_connector_register);
> +
> +/**
> + * drm_connector_unregister - unregister a connector
> + * @connector: the connector to unregister
> + *
> + * Unregister userspace interfaces for a connector
> + */
> +void drm_connector_unregister(struct drm_connector *connector)
> +{
> +       if (!connector->registered)
> +               return;
> +
> +       if (connector->funcs->early_unregister)
> +               connector->funcs->early_unregister(connector);
> +
> +       drm_sysfs_connector_remove(connector);
> +       drm_debugfs_connector_remove(connector);
> +
> +       connector->registered = false;
> +}
> +EXPORT_SYMBOL(drm_connector_unregister);
> +
> +void drm_connector_unregister_all(struct drm_device *dev)
> +{
> +       struct drm_connector *connector;
> +
> +       /* FIXME: taking the mode config mutex ends up in a clash with sysfs */
> +       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
> +               drm_connector_unregister(connector);
> +}
> +
> +int drm_connector_register_all(struct drm_device *dev)
> +{
> +       struct drm_connector *connector;
> +       int ret;
> +
> +       /* FIXME: taking the mode config mutex ends up in a clash with
> +        * fbcon/backlight registration */
> +       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> +               ret = drm_connector_register(connector);
> +               if (ret)
> +                       goto err;
> +       }
> +
> +       return 0;
> +
> +err:
> +       mutex_unlock(&dev->mode_config.mutex);
> +       drm_connector_unregister_all(dev);
> +       return ret;
> +}
> +
> +/**
> + * drm_get_connector_status_name - return a string for connector status
> + * @status: connector status to compute name of
> + *
> + * In contrast to the other drm_get_*_name functions this one here returns a
> + * const pointer and hence is threadsafe.
> + */
> +const char *drm_get_connector_status_name(enum drm_connector_status status)
> +{
> +       if (status == connector_status_connected)
> +               return "connected";
> +       else if (status == connector_status_disconnected)
> +               return "disconnected";
> +       else
> +               return "unknown";
> +}
> +EXPORT_SYMBOL(drm_get_connector_status_name);
> +
> +static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
> +       { SubPixelUnknown, "Unknown" },
> +       { SubPixelHorizontalRGB, "Horizontal RGB" },
> +       { SubPixelHorizontalBGR, "Horizontal BGR" },
> +       { SubPixelVerticalRGB, "Vertical RGB" },
> +       { SubPixelVerticalBGR, "Vertical BGR" },
> +       { SubPixelNone, "None" },
> +};
> +
> +/**
> + * drm_get_subpixel_order_name - return a string for a given subpixel enum
> + * @order: enum of subpixel_order
> + *
> + * Note you could abuse this and return something out of bounds, but that
> + * would be a caller error.  No unscrubbed user data should make it here.
> + */
> +const char *drm_get_subpixel_order_name(enum subpixel_order order)
> +{
> +       return drm_subpixel_enum_list[order].name;
> +}
> +EXPORT_SYMBOL(drm_get_subpixel_order_name);
> +
> +static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
> +       { DRM_MODE_DPMS_ON, "On" },
> +       { DRM_MODE_DPMS_STANDBY, "Standby" },
> +       { DRM_MODE_DPMS_SUSPEND, "Suspend" },
> +       { DRM_MODE_DPMS_OFF, "Off" }
> +};
> +DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
> +
> +/* Optional connector properties. */
> +static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
> +       { DRM_MODE_SCALE_NONE, "None" },
> +       { DRM_MODE_SCALE_FULLSCREEN, "Full" },
> +       { DRM_MODE_SCALE_CENTER, "Center" },
> +       { DRM_MODE_SCALE_ASPECT, "Full aspect" },
> +};
> +
> +static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
> +       { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
> +       { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
> +       { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
> +};
> +
> +static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
> +       { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
> +       { DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
> +       { DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
> +};
> +DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
> +
> +static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
> +       { DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
> +       { DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
> +       { DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
> +};
> +DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
> +                drm_dvi_i_subconnector_enum_list)
> +
> +static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
> +       { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
> +       { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
> +};
> +DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
> +
> +static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
> +       { DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
> +       { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
> +       { DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
> +};
> +DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
> +                drm_tv_subconnector_enum_list)
> +
> +int drm_connector_create_standard_properties(struct drm_device *dev)
> +{
> +       struct drm_property *prop;
> +
> +       prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
> +                                  DRM_MODE_PROP_IMMUTABLE,
> +                                  "EDID", 0);
> +       if (!prop)
> +               return -ENOMEM;
> +       dev->mode_config.edid_property = prop;
> +
> +       prop = drm_property_create_enum(dev, 0,
> +                                  "DPMS", drm_dpms_enum_list,
> +                                  ARRAY_SIZE(drm_dpms_enum_list));
> +       if (!prop)
> +               return -ENOMEM;
> +       dev->mode_config.dpms_property = prop;
> +
> +       prop = drm_property_create(dev,
> +                                  DRM_MODE_PROP_BLOB |
> +                                  DRM_MODE_PROP_IMMUTABLE,
> +                                  "PATH", 0);
> +       if (!prop)
> +               return -ENOMEM;
> +       dev->mode_config.path_property = prop;
> +
> +       prop = drm_property_create(dev,
> +                                  DRM_MODE_PROP_BLOB |
> +                                  DRM_MODE_PROP_IMMUTABLE,
> +                                  "TILE", 0);
> +       if (!prop)
> +               return -ENOMEM;
> +       dev->mode_config.tile_property = prop;
> +
> +       return 0;
> +}
> +
> +/**
> + * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
> + * @dev: DRM device
> + *
> + * Called by a driver the first time a DVI-I connector is made.
> + */
> +int drm_mode_create_dvi_i_properties(struct drm_device *dev)
> +{
> +       struct drm_property *dvi_i_selector;
> +       struct drm_property *dvi_i_subconnector;
> +
> +       if (dev->mode_config.dvi_i_select_subconnector_property)
> +               return 0;
> +
> +       dvi_i_selector =
> +               drm_property_create_enum(dev, 0,
> +                                   "select subconnector",
> +                                   drm_dvi_i_select_enum_list,
> +                                   ARRAY_SIZE(drm_dvi_i_select_enum_list));
> +       dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
> +
> +       dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> +                                   "subconnector",
> +                                   drm_dvi_i_subconnector_enum_list,
> +                                   ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
> +       dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
> +
> +/**
> + * drm_create_tv_properties - create TV specific connector properties
> + * @dev: DRM device
> + * @num_modes: number of different TV formats (modes) supported
> + * @modes: array of pointers to strings containing name of each format
> + *
> + * Called by a driver's TV initialization routine, this function creates
> + * the TV specific connector properties for a given device.  Caller is
> + * responsible for allocating a list of format names and passing them to
> + * this routine.
> + */
> +int drm_mode_create_tv_properties(struct drm_device *dev,
> +                                 unsigned int num_modes,
> +                                 const char * const modes[])
> +{
> +       struct drm_property *tv_selector;
> +       struct drm_property *tv_subconnector;
> +       unsigned int i;
> +
> +       if (dev->mode_config.tv_select_subconnector_property)
> +               return 0;
> +
> +       /*
> +        * Basic connector properties
> +        */
> +       tv_selector = drm_property_create_enum(dev, 0,
> +                                         "select subconnector",
> +                                         drm_tv_select_enum_list,
> +                                         ARRAY_SIZE(drm_tv_select_enum_list));
> +       if (!tv_selector)
> +               goto nomem;
> +
> +       dev->mode_config.tv_select_subconnector_property = tv_selector;
> +
> +       tv_subconnector =
> +               drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> +                                   "subconnector",
> +                                   drm_tv_subconnector_enum_list,
> +                                   ARRAY_SIZE(drm_tv_subconnector_enum_list));
> +       if (!tv_subconnector)
> +               goto nomem;
> +       dev->mode_config.tv_subconnector_property = tv_subconnector;
> +
> +       /*
> +        * Other, TV specific properties: margins & TV modes.
> +        */
> +       dev->mode_config.tv_left_margin_property =
> +               drm_property_create_range(dev, 0, "left margin", 0, 100);
> +       if (!dev->mode_config.tv_left_margin_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_right_margin_property =
> +               drm_property_create_range(dev, 0, "right margin", 0, 100);
> +       if (!dev->mode_config.tv_right_margin_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_top_margin_property =
> +               drm_property_create_range(dev, 0, "top margin", 0, 100);
> +       if (!dev->mode_config.tv_top_margin_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_bottom_margin_property =
> +               drm_property_create_range(dev, 0, "bottom margin", 0, 100);
> +       if (!dev->mode_config.tv_bottom_margin_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_mode_property =
> +               drm_property_create(dev, DRM_MODE_PROP_ENUM,
> +                                   "mode", num_modes);
> +       if (!dev->mode_config.tv_mode_property)
> +               goto nomem;
> +
> +       for (i = 0; i < num_modes; i++)
> +               drm_property_add_enum(dev->mode_config.tv_mode_property, i,
> +                                     i, modes[i]);
> +
> +       dev->mode_config.tv_brightness_property =
> +               drm_property_create_range(dev, 0, "brightness", 0, 100);
> +       if (!dev->mode_config.tv_brightness_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_contrast_property =
> +               drm_property_create_range(dev, 0, "contrast", 0, 100);
> +       if (!dev->mode_config.tv_contrast_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_flicker_reduction_property =
> +               drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
> +       if (!dev->mode_config.tv_flicker_reduction_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_overscan_property =
> +               drm_property_create_range(dev, 0, "overscan", 0, 100);
> +       if (!dev->mode_config.tv_overscan_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_saturation_property =
> +               drm_property_create_range(dev, 0, "saturation", 0, 100);
> +       if (!dev->mode_config.tv_saturation_property)
> +               goto nomem;
> +
> +       dev->mode_config.tv_hue_property =
> +               drm_property_create_range(dev, 0, "hue", 0, 100);
> +       if (!dev->mode_config.tv_hue_property)
> +               goto nomem;
> +
> +       return 0;
> +nomem:
> +       return -ENOMEM;
> +}
> +EXPORT_SYMBOL(drm_mode_create_tv_properties);
> +
> +/**
> + * drm_mode_create_scaling_mode_property - create scaling mode property
> + * @dev: DRM device
> + *
> + * Called by a driver the first time it's needed, must be attached to desired
> + * connectors.
> + */
> +int drm_mode_create_scaling_mode_property(struct drm_device *dev)
> +{
> +       struct drm_property *scaling_mode;
> +
> +       if (dev->mode_config.scaling_mode_property)
> +               return 0;
> +
> +       scaling_mode =
> +               drm_property_create_enum(dev, 0, "scaling mode",
> +                               drm_scaling_mode_enum_list,
> +                                   ARRAY_SIZE(drm_scaling_mode_enum_list));
> +
> +       dev->mode_config.scaling_mode_property = scaling_mode;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
> +
> +/**
> + * drm_mode_create_aspect_ratio_property - create aspect ratio property
> + * @dev: DRM device
> + *
> + * Called by a driver the first time it's needed, must be attached to desired
> + * connectors.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
> +{
> +       if (dev->mode_config.aspect_ratio_property)
> +               return 0;
> +
> +       dev->mode_config.aspect_ratio_property =
> +               drm_property_create_enum(dev, 0, "aspect ratio",
> +                               drm_aspect_ratio_enum_list,
> +                               ARRAY_SIZE(drm_aspect_ratio_enum_list));
> +
> +       if (dev->mode_config.aspect_ratio_property == NULL)
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
> +
> +/**
> + * drm_mode_create_suggested_offset_properties - create suggests offset properties
> + * @dev: DRM device
> + *
> + * Create the the suggested x/y offset property for connectors.
> + */
> +int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
> +{
> +       if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
> +               return 0;
> +
> +       dev->mode_config.suggested_x_property =
> +               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
> +
> +       dev->mode_config.suggested_y_property =
> +               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
> +
> +       if (dev->mode_config.suggested_x_property == NULL ||
> +           dev->mode_config.suggested_y_property == NULL)
> +               return -ENOMEM;
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
> +
> +/**
> + * drm_mode_connector_set_path_property - set tile property on connector
> + * @connector: connector to set property on.
> + * @path: path to use for property; must not be NULL.
> + *
> + * This creates a property to expose to userspace to specify a
> + * connector path. This is mainly used for DisplayPort MST where
> + * connectors have a topology and we want to allow userspace to give
> + * them more meaningful names.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_connector_set_path_property(struct drm_connector *connector,
> +                                        const char *path)
> +{
> +       struct drm_device *dev = connector->dev;
> +       int ret;
> +
> +       ret = drm_property_replace_global_blob(dev,
> +                                              &connector->path_blob_ptr,
> +                                              strlen(path) + 1,
> +                                              path,
> +                                              &connector->base,
> +                                              dev->mode_config.path_property);
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_mode_connector_set_path_property);
> +
> +/**
> + * drm_mode_connector_set_tile_property - set tile property on connector
> + * @connector: connector to set property on.
> + *
> + * This looks up the tile information for a connector, and creates a
> + * property for userspace to parse if it exists. The property is of
> + * the form of 8 integers using ':' as a separator.
> + *
> + * Returns:
> + * Zero on success, errno on failure.
> + */
> +int drm_mode_connector_set_tile_property(struct drm_connector *connector)
> +{
> +       struct drm_device *dev = connector->dev;
> +       char tile[256];
> +       int ret;
> +
> +       if (!connector->has_tile) {
> +               ret  = drm_property_replace_global_blob(dev,
> +                                                       &connector->tile_blob_ptr,
> +                                                       0,
> +                                                       NULL,
> +                                                       &connector->base,
> +                                                       dev->mode_config.tile_property);
> +               return ret;
> +       }
> +
> +       snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
> +                connector->tile_group->id, connector->tile_is_single_monitor,
> +                connector->num_h_tile, connector->num_v_tile,
> +                connector->tile_h_loc, connector->tile_v_loc,
> +                connector->tile_h_size, connector->tile_v_size);
> +
> +       ret = drm_property_replace_global_blob(dev,
> +                                              &connector->tile_blob_ptr,
> +                                              strlen(tile) + 1,
> +                                              tile,
> +                                              &connector->base,
> +                                              dev->mode_config.tile_property);
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
> +
> +/**
> + * drm_mode_connector_update_edid_property - update the edid property of a connector
> + * @connector: drm connector
> + * @edid: new value of the edid property
> + *
> + * This function creates a new blob modeset object and assigns its id to the
> + * connector's edid property.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_connector_update_edid_property(struct drm_connector *connector,
> +                                           const struct edid *edid)
> +{
> +       struct drm_device *dev = connector->dev;
> +       size_t size = 0;
> +       int ret;
> +
> +       /* ignore requests to set edid when overridden */
> +       if (connector->override_edid)
> +               return 0;
> +
> +       if (edid)
> +               size = EDID_LENGTH * (1 + edid->extensions);
> +
> +       ret = drm_property_replace_global_blob(dev,
> +                                              &connector->edid_blob_ptr,
> +                                              size,
> +                                              edid,
> +                                              &connector->base,
> +                                              dev->mode_config.edid_property);
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
> +
> +int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
> +                                   struct drm_property *property,
> +                                   uint64_t value)
> +{
> +       int ret = -EINVAL;
> +       struct drm_connector *connector = obj_to_connector(obj);
> +
> +       /* Do DPMS ourselves */
> +       if (property == connector->dev->mode_config.dpms_property) {
> +               ret = (*connector->funcs->dpms)(connector, (int)value);
> +       } else if (connector->funcs->set_property)
> +               ret = connector->funcs->set_property(connector, property, value);

Can you add a brace here, too?

> +
> +       /* store the property value if successful */
> +       if (!ret)
> +               drm_object_property_set_value(&connector->base, property, value);
> +       return ret;
> +}
> +
> +int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
> +                                      void *data, struct drm_file *file_priv)
> +{
> +       struct drm_mode_connector_set_property *conn_set_prop = data;
> +       struct drm_mode_obj_set_property obj_set_prop = {
> +               .value = conn_set_prop->value,
> +               .prop_id = conn_set_prop->prop_id,
> +               .obj_id = conn_set_prop->connector_id,
> +               .obj_type = DRM_MODE_OBJECT_CONNECTOR
> +       };
> +
> +       /* It does all the locking and checking we need */
> +       return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
> +}
> +
> +static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
> +{
> +       /* For atomic drivers only state objects are synchronously updated and
> +        * protected by modeset locks, so check those first. */
> +       if (connector->state)
> +               return connector->state->best_encoder;
> +       return connector->encoder;
> +}
> +
> +static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
> +                                        const struct drm_file *file_priv)
> +{
> +       /*
> +        * If user-space hasn't configured the driver to expose the stereo 3D
> +        * modes, don't expose them.
> +        */
> +       if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
> +               return false;
> +
> +       return true;
> +}
> +
> +int drm_mode_getconnector(struct drm_device *dev, void *data,
> +                         struct drm_file *file_priv)
> +{
> +       struct drm_mode_get_connector *out_resp = data;
> +       struct drm_connector *connector;
> +       struct drm_encoder *encoder;
> +       struct drm_display_mode *mode;
> +       int mode_count = 0;
> +       int encoders_count = 0;
> +       int ret = 0;
> +       int copied = 0;
> +       int i;
> +       struct drm_mode_modeinfo u_mode;
> +       struct drm_mode_modeinfo __user *mode_ptr;
> +       uint32_t __user *encoder_ptr;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +               return -EINVAL;
> +
> +       memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
> +
> +       mutex_lock(&dev->mode_config.mutex);
> +
> +       connector = drm_connector_lookup(dev, out_resp->connector_id);
> +       if (!connector) {
> +               ret = -ENOENT;
> +               goto out_unlock;
> +       }
> +
> +       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
> +               if (connector->encoder_ids[i] != 0)
> +                       encoders_count++;
> +
> +       if (out_resp->count_modes == 0) {
> +               connector->funcs->fill_modes(connector,
> +                                            dev->mode_config.max_width,
> +                                            dev->mode_config.max_height);
> +       }
> +
> +       /* delayed so we get modes regardless of pre-fill_modes state */
> +       list_for_each_entry(mode, &connector->modes, head)
> +               if (drm_mode_expose_to_userspace(mode, file_priv))
> +                       mode_count++;
> +
> +       out_resp->connector_id = connector->base.id;
> +       out_resp->connector_type = connector->connector_type;
> +       out_resp->connector_type_id = connector->connector_type_id;
> +       out_resp->mm_width = connector->display_info.width_mm;
> +       out_resp->mm_height = connector->display_info.height_mm;
> +       out_resp->subpixel = connector->display_info.subpixel_order;
> +       out_resp->connection = connector->status;
> +
> +       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> +       encoder = drm_connector_get_encoder(connector);
> +       if (encoder)
> +               out_resp->encoder_id = encoder->base.id;
> +       else
> +               out_resp->encoder_id = 0;
> +
> +       /*
> +        * This ioctl is called twice, once to determine how much space is
> +        * needed, and the 2nd time to fill it.
> +        */
> +       if ((out_resp->count_modes >= mode_count) && mode_count) {
> +               copied = 0;
> +               mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
> +               list_for_each_entry(mode, &connector->modes, head) {
> +                       if (!drm_mode_expose_to_userspace(mode, file_priv))
> +                               continue;
> +
> +                       drm_mode_convert_to_umode(&u_mode, mode);
> +                       if (copy_to_user(mode_ptr + copied,
> +                                        &u_mode, sizeof(u_mode))) {
> +                               ret = -EFAULT;
> +                               goto out;
> +                       }
> +                       copied++;
> +               }
> +       }
> +       out_resp->count_modes = mode_count;
> +
> +       ret = drm_mode_object_get_properties(&connector->base, file_priv->atomic,
> +                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> +                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> +                       &out_resp->count_props);
> +       if (ret)
> +               goto out;
> +
> +       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> +               copied = 0;
> +               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> +               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> +                       if (connector->encoder_ids[i] != 0) {
> +                               if (put_user(connector->encoder_ids[i],
> +                                            encoder_ptr + copied)) {
> +                                       ret = -EFAULT;
> +                                       goto out;
> +                               }
> +                               copied++;
> +                       }
> +               }
> +       }
> +       out_resp->count_encoders = encoders_count;
> +
> +out:
> +       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> +
> +       drm_connector_unreference(connector);
> +out_unlock:
> +       mutex_unlock(&dev->mode_config.mutex);
> +
> +       return ret;
> +}
> +
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 165a0f9308da..69b5626141f5 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -45,123 +45,15 @@
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
>
> -/* Avoid boilerplate.  I'm tired of typing. */
> -#define DRM_ENUM_NAME_FN(fnname, list)                         \
> -       const char *fnname(int val)                             \
> -       {                                                       \
> -               int i;                                          \
> -               for (i = 0; i < ARRAY_SIZE(list); i++) {        \
> -                       if (list[i].type == val)                \
> -                               return list[i].name;            \
> -               }                                               \
> -               return "(unknown)";                             \
> -       }
> -
>  /*
>   * Global properties
>   */
> -static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
> -       { DRM_MODE_DPMS_ON, "On" },
> -       { DRM_MODE_DPMS_STANDBY, "Standby" },
> -       { DRM_MODE_DPMS_SUSPEND, "Suspend" },
> -       { DRM_MODE_DPMS_OFF, "Off" }
> -};
> -
> -DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
> -
>  static const struct drm_prop_enum_list drm_plane_type_enum_list[] = {
>         { DRM_PLANE_TYPE_OVERLAY, "Overlay" },
>         { DRM_PLANE_TYPE_PRIMARY, "Primary" },
>         { DRM_PLANE_TYPE_CURSOR, "Cursor" },
>  };
>
> -/*
> - * Optional properties
> - */
> -static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
> -       { DRM_MODE_SCALE_NONE, "None" },
> -       { DRM_MODE_SCALE_FULLSCREEN, "Full" },
> -       { DRM_MODE_SCALE_CENTER, "Center" },
> -       { DRM_MODE_SCALE_ASPECT, "Full aspect" },
> -};
> -
> -static const struct drm_prop_enum_list drm_aspect_ratio_enum_list[] = {
> -       { DRM_MODE_PICTURE_ASPECT_NONE, "Automatic" },
> -       { DRM_MODE_PICTURE_ASPECT_4_3, "4:3" },
> -       { DRM_MODE_PICTURE_ASPECT_16_9, "16:9" },
> -};
> -
> -/*
> - * Non-global properties, but "required" for certain connectors.
> - */
> -static const struct drm_prop_enum_list drm_dvi_i_select_enum_list[] = {
> -       { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
> -       { DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
> -       { DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
> -};
> -
> -DRM_ENUM_NAME_FN(drm_get_dvi_i_select_name, drm_dvi_i_select_enum_list)
> -
> -static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = {
> -       { DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
> -       { DRM_MODE_SUBCONNECTOR_DVID,      "DVI-D"     }, /* DVI-I  */
> -       { DRM_MODE_SUBCONNECTOR_DVIA,      "DVI-A"     }, /* DVI-I  */
> -};
> -
> -DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name,
> -                drm_dvi_i_subconnector_enum_list)
> -
> -static const struct drm_prop_enum_list drm_tv_select_enum_list[] = {
> -       { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */
> -       { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
> -};
> -
> -DRM_ENUM_NAME_FN(drm_get_tv_select_name, drm_tv_select_enum_list)
> -
> -static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
> -       { DRM_MODE_SUBCONNECTOR_Unknown,   "Unknown"   }, /* DVI-I and TV-out */
> -       { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_SVIDEO,    "SVIDEO"    }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_Component, "Component" }, /* TV-out */
> -       { DRM_MODE_SUBCONNECTOR_SCART,     "SCART"     }, /* TV-out */
> -};
> -
> -DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
> -                drm_tv_subconnector_enum_list)
> -
> -struct drm_conn_prop_enum_list {
> -       int type;
> -       const char *name;
> -       struct ida ida;
> -};
> -
> -/*
> - * Connector and encoder types.
> - */
> -static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
> -       { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
> -       { DRM_MODE_CONNECTOR_VGA, "VGA" },
> -       { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
> -       { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
> -       { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
> -       { DRM_MODE_CONNECTOR_Composite, "Composite" },
> -       { DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
> -       { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
> -       { DRM_MODE_CONNECTOR_Component, "Component" },
> -       { DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
> -       { DRM_MODE_CONNECTOR_DisplayPort, "DP" },
> -       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
> -       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
> -       { DRM_MODE_CONNECTOR_TV, "TV" },
> -       { DRM_MODE_CONNECTOR_eDP, "eDP" },
> -       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
> -       { DRM_MODE_CONNECTOR_DSI, "DSI" },
> -       { DRM_MODE_CONNECTOR_DPI, "DPI" },
> -};
> -
>  static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
>         { DRM_MODE_ENCODER_NONE, "None" },
>         { DRM_MODE_ENCODER_DAC, "DAC" },
> @@ -174,62 +66,9 @@ static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
>         { DRM_MODE_ENCODER_DPI, "DPI" },
>  };
>
> -static const struct drm_prop_enum_list drm_subpixel_enum_list[] = {
> -       { SubPixelUnknown, "Unknown" },
> -       { SubPixelHorizontalRGB, "Horizontal RGB" },
> -       { SubPixelHorizontalBGR, "Horizontal BGR" },
> -       { SubPixelVerticalRGB, "Vertical RGB" },
> -       { SubPixelVerticalBGR, "Vertical BGR" },
> -       { SubPixelNone, "None" },
> -};
> -
> -void drm_connector_ida_init(void)
> -{
> -       int i;
> -
> -       for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
> -               ida_init(&drm_connector_enum_list[i].ida);
> -}
> -
> -void drm_connector_ida_destroy(void)
> -{
> -       int i;
> -
> -       for (i = 0; i < ARRAY_SIZE(drm_connector_enum_list); i++)
> -               ida_destroy(&drm_connector_enum_list[i].ida);
> -}
> -
> -/**
> - * drm_get_connector_status_name - return a string for connector status
> - * @status: connector status to compute name of
> - *
> - * In contrast to the other drm_get_*_name functions this one here returns a
> - * const pointer and hence is threadsafe.
> - */
> -const char *drm_get_connector_status_name(enum drm_connector_status status)
> -{
> -       if (status == connector_status_connected)
> -               return "connected";
> -       else if (status == connector_status_disconnected)
> -               return "disconnected";
> -       else
> -               return "unknown";
> -}
> -EXPORT_SYMBOL(drm_get_connector_status_name);
> -
> -/**
> - * drm_get_subpixel_order_name - return a string for a given subpixel enum
> - * @order: enum of subpixel_order
> - *
> - * Note you could abuse this and return something out of bounds, but that
> - * would be a caller error.  No unscrubbed user data should make it here.
> +/*
> + * Optional properties
>   */
> -const char *drm_get_subpixel_order_name(enum subpixel_order order)
> -{
> -       return drm_subpixel_enum_list[order].name;
> -}
> -EXPORT_SYMBOL(drm_get_subpixel_order_name);
> -
>  /*
>   * Internal function to assign a slot in the object idr and optionally
>   * register the object into the idr.
> @@ -552,20 +391,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
>  }
>  EXPORT_SYMBOL(drm_crtc_cleanup);
>
> -/*
> - * drm_mode_remove - remove and free a mode
> - * @connector: connector list to modify
> - * @mode: mode to remove
> - *
> - * Remove @mode from @connector's mode list, then free it.
> - */
> -static void drm_mode_remove(struct drm_connector *connector,
> -                           struct drm_display_mode *mode)
> -{
> -       list_del(&mode->head);
> -       drm_mode_destroy(connector->dev, mode);
> -}
> -
>  /**
>   * drm_display_info_set_bus_formats - set the supported bus formats
>   * @info: display info to store bus formats in
> @@ -600,312 +425,6 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
>  }
>  EXPORT_SYMBOL(drm_display_info_set_bus_formats);
>
> -/**
> - * drm_connector_get_cmdline_mode - reads the user's cmdline mode
> - * @connector: connector to quwery
> - *
> - * The kernel supports per-connector configration of its consoles through
> - * use of the video= parameter. This function parses that option and
> - * extracts the user's specified mode (or enable/disable status) for a
> - * particular connector. This is typically only used during the early fbdev
> - * setup.
> - */
> -static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
> -{
> -       struct drm_cmdline_mode *mode = &connector->cmdline_mode;
> -       char *option = NULL;
> -
> -       if (fb_get_options(connector->name, &option))
> -               return;
> -
> -       if (!drm_mode_parse_command_line_for_connector(option,
> -                                                      connector,
> -                                                      mode))
> -               return;
> -
> -       if (mode->force) {
> -               const char *s;
> -
> -               switch (mode->force) {
> -               case DRM_FORCE_OFF:
> -                       s = "OFF";
> -                       break;
> -               case DRM_FORCE_ON_DIGITAL:
> -                       s = "ON - dig";
> -                       break;
> -               default:
> -               case DRM_FORCE_ON:
> -                       s = "ON";
> -                       break;
> -               }
> -
> -               DRM_INFO("forcing %s connector %s\n", connector->name, s);
> -               connector->force = mode->force;
> -       }
> -
> -       DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
> -                     connector->name,
> -                     mode->xres, mode->yres,
> -                     mode->refresh_specified ? mode->refresh : 60,
> -                     mode->rb ? " reduced blanking" : "",
> -                     mode->margins ? " with margins" : "",
> -                     mode->interlace ?  " interlaced" : "");
> -}
> -
> -static void drm_connector_free(struct kref *kref)
> -{
> -       struct drm_connector *connector =
> -               container_of(kref, struct drm_connector, base.refcount);
> -       struct drm_device *dev = connector->dev;
> -
> -       drm_mode_object_unregister(dev, &connector->base);
> -       connector->funcs->destroy(connector);
> -}
> -
> -/**
> - * drm_connector_init - Init a preallocated connector
> - * @dev: DRM device
> - * @connector: the connector to init
> - * @funcs: callbacks for this connector
> - * @connector_type: user visible type of the connector
> - *
> - * Initialises a preallocated connector. Connectors should be
> - * subclassed as part of driver connector objects.
> - *
> - * Returns:
> - * Zero on success, error code on failure.
> - */
> -int drm_connector_init(struct drm_device *dev,
> -                      struct drm_connector *connector,
> -                      const struct drm_connector_funcs *funcs,
> -                      int connector_type)
> -{
> -       struct drm_mode_config *config = &dev->mode_config;
> -       int ret;
> -       struct ida *connector_ida =
> -               &drm_connector_enum_list[connector_type].ida;
> -
> -       drm_modeset_lock_all(dev);
> -
> -       ret = drm_mode_object_get_reg(dev, &connector->base,
> -                                     DRM_MODE_OBJECT_CONNECTOR,
> -                                     false, drm_connector_free);
> -       if (ret)
> -               goto out_unlock;
> -
> -       connector->base.properties = &connector->properties;
> -       connector->dev = dev;
> -       connector->funcs = funcs;
> -
> -       ret = ida_simple_get(&config->connector_ida, 0, 0, GFP_KERNEL);
> -       if (ret < 0)
> -               goto out_put;
> -       connector->index = ret;
> -       ret = 0;
> -
> -       connector->connector_type = connector_type;
> -       connector->connector_type_id =
> -               ida_simple_get(connector_ida, 1, 0, GFP_KERNEL);
> -       if (connector->connector_type_id < 0) {
> -               ret = connector->connector_type_id;
> -               goto out_put_id;
> -       }
> -       connector->name =
> -               kasprintf(GFP_KERNEL, "%s-%d",
> -                         drm_connector_enum_list[connector_type].name,
> -                         connector->connector_type_id);
> -       if (!connector->name) {
> -               ret = -ENOMEM;
> -               goto out_put_type_id;
> -       }
> -
> -       INIT_LIST_HEAD(&connector->probed_modes);
> -       INIT_LIST_HEAD(&connector->modes);
> -       connector->edid_blob_ptr = NULL;
> -       connector->status = connector_status_unknown;
> -
> -       drm_connector_get_cmdline_mode(connector);
> -
> -       /* We should add connectors at the end to avoid upsetting the connector
> -        * index too much. */
> -       list_add_tail(&connector->head, &config->connector_list);
> -       config->num_connector++;
> -
> -       if (connector_type != DRM_MODE_CONNECTOR_VIRTUAL)
> -               drm_object_attach_property(&connector->base,
> -                                             config->edid_property,
> -                                             0);
> -
> -       drm_object_attach_property(&connector->base,
> -                                     config->dpms_property, 0);
> -
> -       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
> -               drm_object_attach_property(&connector->base, config->prop_crtc_id, 0);
> -       }
> -
> -       connector->debugfs_entry = NULL;
> -out_put_type_id:
> -       if (ret)
> -               ida_remove(connector_ida, connector->connector_type_id);
> -out_put_id:
> -       if (ret)
> -               ida_remove(&config->connector_ida, connector->index);
> -out_put:
> -       if (ret)
> -               drm_mode_object_unregister(dev, &connector->base);
> -
> -out_unlock:
> -       drm_modeset_unlock_all(dev);
> -
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_connector_init);
> -
> -/**
> - * drm_connector_cleanup - cleans up an initialised connector
> - * @connector: connector to cleanup
> - *
> - * Cleans up the connector but doesn't free the object.
> - */
> -void drm_connector_cleanup(struct drm_connector *connector)
> -{
> -       struct drm_device *dev = connector->dev;
> -       struct drm_display_mode *mode, *t;
> -
> -       /* The connector should have been removed from userspace long before
> -        * it is finally destroyed.
> -        */
> -       if (WARN_ON(connector->registered))
> -               drm_connector_unregister(connector);
> -
> -       if (connector->tile_group) {
> -               drm_mode_put_tile_group(dev, connector->tile_group);
> -               connector->tile_group = NULL;
> -       }
> -
> -       list_for_each_entry_safe(mode, t, &connector->probed_modes, head)
> -               drm_mode_remove(connector, mode);
> -
> -       list_for_each_entry_safe(mode, t, &connector->modes, head)
> -               drm_mode_remove(connector, mode);
> -
> -       ida_remove(&drm_connector_enum_list[connector->connector_type].ida,
> -                  connector->connector_type_id);
> -
> -       ida_remove(&dev->mode_config.connector_ida,
> -                  connector->index);
> -
> -       kfree(connector->display_info.bus_formats);
> -       drm_mode_object_unregister(dev, &connector->base);
> -       kfree(connector->name);
> -       connector->name = NULL;
> -       list_del(&connector->head);
> -       dev->mode_config.num_connector--;
> -
> -       WARN_ON(connector->state && !connector->funcs->atomic_destroy_state);
> -       if (connector->state && connector->funcs->atomic_destroy_state)
> -               connector->funcs->atomic_destroy_state(connector,
> -                                                      connector->state);
> -
> -       memset(connector, 0, sizeof(*connector));
> -}
> -EXPORT_SYMBOL(drm_connector_cleanup);
> -
> -/**
> - * drm_connector_register - register a connector
> - * @connector: the connector to register
> - *
> - * Register userspace interfaces for a connector
> - *
> - * Returns:
> - * Zero on success, error code on failure.
> - */
> -int drm_connector_register(struct drm_connector *connector)
> -{
> -       int ret;
> -
> -       if (connector->registered)
> -               return 0;
> -
> -       ret = drm_sysfs_connector_add(connector);
> -       if (ret)
> -               return ret;
> -
> -       ret = drm_debugfs_connector_add(connector);
> -       if (ret) {
> -               goto err_sysfs;
> -       }
> -
> -       if (connector->funcs->late_register) {
> -               ret = connector->funcs->late_register(connector);
> -               if (ret)
> -                       goto err_debugfs;
> -       }
> -
> -       drm_mode_object_register(connector->dev, &connector->base);
> -
> -       connector->registered = true;
> -       return 0;
> -
> -err_debugfs:
> -       drm_debugfs_connector_remove(connector);
> -err_sysfs:
> -       drm_sysfs_connector_remove(connector);
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_connector_register);
> -
> -/**
> - * drm_connector_unregister - unregister a connector
> - * @connector: the connector to unregister
> - *
> - * Unregister userspace interfaces for a connector
> - */
> -void drm_connector_unregister(struct drm_connector *connector)
> -{
> -       if (!connector->registered)
> -               return;
> -
> -       if (connector->funcs->early_unregister)
> -               connector->funcs->early_unregister(connector);
> -
> -       drm_sysfs_connector_remove(connector);
> -       drm_debugfs_connector_remove(connector);
> -
> -       connector->registered = false;
> -}
> -EXPORT_SYMBOL(drm_connector_unregister);
> -
> -static void drm_connector_unregister_all(struct drm_device *dev)
> -{
> -       struct drm_connector *connector;
> -
> -       /* FIXME: taking the mode config mutex ends up in a clash with sysfs */
> -       list_for_each_entry(connector, &dev->mode_config.connector_list, head)
> -               drm_connector_unregister(connector);
> -}
> -
> -static int drm_connector_register_all(struct drm_device *dev)
> -{
> -       struct drm_connector *connector;
> -       int ret;
> -
> -       /* FIXME: taking the mode config mutex ends up in a clash with
> -        * fbcon/backlight registration */
> -       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
> -               ret = drm_connector_register(connector);
> -               if (ret)
> -                       goto err;
> -       }
> -
> -       return 0;
> -
> -err:
> -       mutex_unlock(&dev->mode_config.mutex);
> -       drm_connector_unregister_all(dev);
> -       return ret;
> -}
> -
>  static int drm_encoder_register_all(struct drm_device *dev)
>  {
>         struct drm_encoder *encoder;
> @@ -1309,39 +828,11 @@ void drm_modeset_unregister_all(struct drm_device *dev)
>  static int drm_mode_create_standard_properties(struct drm_device *dev)
>  {
>         struct drm_property *prop;
> +       int ret;
>
> -       /*
> -        * Standard properties (apply to all connectors)
> -        */
> -       prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
> -                                  DRM_MODE_PROP_IMMUTABLE,
> -                                  "EDID", 0);
> -       if (!prop)
> -               return -ENOMEM;
> -       dev->mode_config.edid_property = prop;
> -
> -       prop = drm_property_create_enum(dev, 0,
> -                                  "DPMS", drm_dpms_enum_list,
> -                                  ARRAY_SIZE(drm_dpms_enum_list));
> -       if (!prop)
> -               return -ENOMEM;
> -       dev->mode_config.dpms_property = prop;
> -
> -       prop = drm_property_create(dev,
> -                                  DRM_MODE_PROP_BLOB |
> -                                  DRM_MODE_PROP_IMMUTABLE,
> -                                  "PATH", 0);
> -       if (!prop)
> -               return -ENOMEM;
> -       dev->mode_config.path_property = prop;
> -
> -       prop = drm_property_create(dev,
> -                                  DRM_MODE_PROP_BLOB |
> -                                  DRM_MODE_PROP_IMMUTABLE,
> -                                  "TILE", 0);
> -       if (!prop)
> -               return -ENOMEM;
> -       dev->mode_config.tile_property = prop;
> +       ret = drm_connector_create_standard_properties(dev);
> +       if (ret)
> +               return ret;
>
>         prop = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
>                                         "type", drm_plane_type_enum_list,
> @@ -1462,225 +953,6 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
>  }
>
>  /**
> - * drm_mode_create_dvi_i_properties - create DVI-I specific connector properties
> - * @dev: DRM device
> - *
> - * Called by a driver the first time a DVI-I connector is made.
> - */
> -int drm_mode_create_dvi_i_properties(struct drm_device *dev)
> -{
> -       struct drm_property *dvi_i_selector;
> -       struct drm_property *dvi_i_subconnector;
> -
> -       if (dev->mode_config.dvi_i_select_subconnector_property)
> -               return 0;
> -
> -       dvi_i_selector =
> -               drm_property_create_enum(dev, 0,
> -                                   "select subconnector",
> -                                   drm_dvi_i_select_enum_list,
> -                                   ARRAY_SIZE(drm_dvi_i_select_enum_list));
> -       dev->mode_config.dvi_i_select_subconnector_property = dvi_i_selector;
> -
> -       dvi_i_subconnector = drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> -                                   "subconnector",
> -                                   drm_dvi_i_subconnector_enum_list,
> -                                   ARRAY_SIZE(drm_dvi_i_subconnector_enum_list));
> -       dev->mode_config.dvi_i_subconnector_property = dvi_i_subconnector;
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL(drm_mode_create_dvi_i_properties);
> -
> -/**
> - * drm_create_tv_properties - create TV specific connector properties
> - * @dev: DRM device
> - * @num_modes: number of different TV formats (modes) supported
> - * @modes: array of pointers to strings containing name of each format
> - *
> - * Called by a driver's TV initialization routine, this function creates
> - * the TV specific connector properties for a given device.  Caller is
> - * responsible for allocating a list of format names and passing them to
> - * this routine.
> - */
> -int drm_mode_create_tv_properties(struct drm_device *dev,
> -                                 unsigned int num_modes,
> -                                 const char * const modes[])
> -{
> -       struct drm_property *tv_selector;
> -       struct drm_property *tv_subconnector;
> -       unsigned int i;
> -
> -       if (dev->mode_config.tv_select_subconnector_property)
> -               return 0;
> -
> -       /*
> -        * Basic connector properties
> -        */
> -       tv_selector = drm_property_create_enum(dev, 0,
> -                                         "select subconnector",
> -                                         drm_tv_select_enum_list,
> -                                         ARRAY_SIZE(drm_tv_select_enum_list));
> -       if (!tv_selector)
> -               goto nomem;
> -
> -       dev->mode_config.tv_select_subconnector_property = tv_selector;
> -
> -       tv_subconnector =
> -               drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
> -                                   "subconnector",
> -                                   drm_tv_subconnector_enum_list,
> -                                   ARRAY_SIZE(drm_tv_subconnector_enum_list));
> -       if (!tv_subconnector)
> -               goto nomem;
> -       dev->mode_config.tv_subconnector_property = tv_subconnector;
> -
> -       /*
> -        * Other, TV specific properties: margins & TV modes.
> -        */
> -       dev->mode_config.tv_left_margin_property =
> -               drm_property_create_range(dev, 0, "left margin", 0, 100);
> -       if (!dev->mode_config.tv_left_margin_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_right_margin_property =
> -               drm_property_create_range(dev, 0, "right margin", 0, 100);
> -       if (!dev->mode_config.tv_right_margin_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_top_margin_property =
> -               drm_property_create_range(dev, 0, "top margin", 0, 100);
> -       if (!dev->mode_config.tv_top_margin_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_bottom_margin_property =
> -               drm_property_create_range(dev, 0, "bottom margin", 0, 100);
> -       if (!dev->mode_config.tv_bottom_margin_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_mode_property =
> -               drm_property_create(dev, DRM_MODE_PROP_ENUM,
> -                                   "mode", num_modes);
> -       if (!dev->mode_config.tv_mode_property)
> -               goto nomem;
> -
> -       for (i = 0; i < num_modes; i++)
> -               drm_property_add_enum(dev->mode_config.tv_mode_property, i,
> -                                     i, modes[i]);
> -
> -       dev->mode_config.tv_brightness_property =
> -               drm_property_create_range(dev, 0, "brightness", 0, 100);
> -       if (!dev->mode_config.tv_brightness_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_contrast_property =
> -               drm_property_create_range(dev, 0, "contrast", 0, 100);
> -       if (!dev->mode_config.tv_contrast_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_flicker_reduction_property =
> -               drm_property_create_range(dev, 0, "flicker reduction", 0, 100);
> -       if (!dev->mode_config.tv_flicker_reduction_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_overscan_property =
> -               drm_property_create_range(dev, 0, "overscan", 0, 100);
> -       if (!dev->mode_config.tv_overscan_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_saturation_property =
> -               drm_property_create_range(dev, 0, "saturation", 0, 100);
> -       if (!dev->mode_config.tv_saturation_property)
> -               goto nomem;
> -
> -       dev->mode_config.tv_hue_property =
> -               drm_property_create_range(dev, 0, "hue", 0, 100);
> -       if (!dev->mode_config.tv_hue_property)
> -               goto nomem;
> -
> -       return 0;
> -nomem:
> -       return -ENOMEM;
> -}
> -EXPORT_SYMBOL(drm_mode_create_tv_properties);
> -
> -/**
> - * drm_mode_create_scaling_mode_property - create scaling mode property
> - * @dev: DRM device
> - *
> - * Called by a driver the first time it's needed, must be attached to desired
> - * connectors.
> - */
> -int drm_mode_create_scaling_mode_property(struct drm_device *dev)
> -{
> -       struct drm_property *scaling_mode;
> -
> -       if (dev->mode_config.scaling_mode_property)
> -               return 0;
> -
> -       scaling_mode =
> -               drm_property_create_enum(dev, 0, "scaling mode",
> -                               drm_scaling_mode_enum_list,
> -                                   ARRAY_SIZE(drm_scaling_mode_enum_list));
> -
> -       dev->mode_config.scaling_mode_property = scaling_mode;
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
> -
> -/**
> - * drm_mode_create_aspect_ratio_property - create aspect ratio property
> - * @dev: DRM device
> - *
> - * Called by a driver the first time it's needed, must be attached to desired
> - * connectors.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
> -{
> -       if (dev->mode_config.aspect_ratio_property)
> -               return 0;
> -
> -       dev->mode_config.aspect_ratio_property =
> -               drm_property_create_enum(dev, 0, "aspect ratio",
> -                               drm_aspect_ratio_enum_list,
> -                               ARRAY_SIZE(drm_aspect_ratio_enum_list));
> -
> -       if (dev->mode_config.aspect_ratio_property == NULL)
> -               return -ENOMEM;
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
> -
> -/**
> - * drm_mode_create_suggested_offset_properties - create suggests offset properties
> - * @dev: DRM device
> - *
> - * Create the the suggested x/y offset property for connectors.
> - */
> -int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
> -{
> -       if (dev->mode_config.suggested_x_property && dev->mode_config.suggested_y_property)
> -               return 0;
> -
> -       dev->mode_config.suggested_x_property =
> -               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested X", 0, 0xffffffff);
> -
> -       dev->mode_config.suggested_y_property =
> -               drm_property_create_range(dev, DRM_MODE_PROP_IMMUTABLE, "suggested Y", 0, 0xffffffff);
> -
> -       if (dev->mode_config.suggested_x_property == NULL ||
> -           dev->mode_config.suggested_y_property == NULL)
> -               return -ENOMEM;
> -       return 0;
> -}
> -EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);
> -
> -/**
>   * drm_mode_getresources - get graphics configuration
>   * @dev: drm device for the ioctl
>   * @data: data pointer for the ioctl
> @@ -1862,32 +1134,11 @@ int drm_mode_getcrtc(struct drm_device *dev,
>         return 0;
>  }
>
> -static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
> -                                        const struct drm_file *file_priv)
> -{
> -       /*
> -        * If user-space hasn't configured the driver to expose the stereo 3D
> -        * modes, don't expose them.
> -        */
> -       if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
> -               return false;
> -
> -       return true;
> -}
> -
> -static struct drm_encoder *drm_connector_get_encoder(struct drm_connector *connector)
> -{
> -       /* For atomic drivers only state objects are synchronously updated and
> -        * protected by modeset locks, so check those first. */
> -       if (connector->state)
> -               return connector->state->best_encoder;
> -       return connector->encoder;
> -}
> -
>  /* helper for getconnector and getproperties ioctls */
> -static int get_properties(struct drm_mode_object *obj, bool atomic,
> -               uint32_t __user *prop_ptr, uint64_t __user *prop_values,
> -               uint32_t *arg_count_props)
> +int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
> +                                  uint32_t __user *prop_ptr,
> +                                  uint64_t __user *prop_values,
> +                                  uint32_t *arg_count_props)
>  {
>         int props_count;
>         int i, ret, copied;
> @@ -1922,133 +1173,6 @@ static int get_properties(struct drm_mode_object *obj, bool atomic,
>         return 0;
>  }
>
> -/**
> - * drm_mode_getconnector - get connector configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Construct a connector configuration structure to return to the user.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_getconnector(struct drm_device *dev, void *data,
> -                         struct drm_file *file_priv)
> -{
> -       struct drm_mode_get_connector *out_resp = data;
> -       struct drm_connector *connector;
> -       struct drm_encoder *encoder;
> -       struct drm_display_mode *mode;
> -       int mode_count = 0;
> -       int encoders_count = 0;
> -       int ret = 0;
> -       int copied = 0;
> -       int i;
> -       struct drm_mode_modeinfo u_mode;
> -       struct drm_mode_modeinfo __user *mode_ptr;
> -       uint32_t __user *encoder_ptr;
> -
> -       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> -               return -EINVAL;
> -
> -       memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
> -
> -       mutex_lock(&dev->mode_config.mutex);
> -
> -       connector = drm_connector_lookup(dev, out_resp->connector_id);
> -       if (!connector) {
> -               ret = -ENOENT;
> -               goto out_unlock;
> -       }
> -
> -       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
> -               if (connector->encoder_ids[i] != 0)
> -                       encoders_count++;
> -
> -       if (out_resp->count_modes == 0) {
> -               connector->funcs->fill_modes(connector,
> -                                            dev->mode_config.max_width,
> -                                            dev->mode_config.max_height);
> -       }
> -
> -       /* delayed so we get modes regardless of pre-fill_modes state */
> -       list_for_each_entry(mode, &connector->modes, head)
> -               if (drm_mode_expose_to_userspace(mode, file_priv))
> -                       mode_count++;
> -
> -       out_resp->connector_id = connector->base.id;
> -       out_resp->connector_type = connector->connector_type;
> -       out_resp->connector_type_id = connector->connector_type_id;
> -       out_resp->mm_width = connector->display_info.width_mm;
> -       out_resp->mm_height = connector->display_info.height_mm;
> -       out_resp->subpixel = connector->display_info.subpixel_order;
> -       out_resp->connection = connector->status;
> -
> -       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> -       encoder = drm_connector_get_encoder(connector);
> -       if (encoder)
> -               out_resp->encoder_id = encoder->base.id;
> -       else
> -               out_resp->encoder_id = 0;
> -
> -       /*
> -        * This ioctl is called twice, once to determine how much space is
> -        * needed, and the 2nd time to fill it.
> -        */
> -       if ((out_resp->count_modes >= mode_count) && mode_count) {
> -               copied = 0;
> -               mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
> -               list_for_each_entry(mode, &connector->modes, head) {
> -                       if (!drm_mode_expose_to_userspace(mode, file_priv))
> -                               continue;
> -
> -                       drm_mode_convert_to_umode(&u_mode, mode);
> -                       if (copy_to_user(mode_ptr + copied,
> -                                        &u_mode, sizeof(u_mode))) {
> -                               ret = -EFAULT;
> -                               goto out;
> -                       }
> -                       copied++;
> -               }
> -       }
> -       out_resp->count_modes = mode_count;
> -
> -       ret = get_properties(&connector->base, file_priv->atomic,
> -                       (uint32_t __user *)(unsigned long)(out_resp->props_ptr),
> -                       (uint64_t __user *)(unsigned long)(out_resp->prop_values_ptr),
> -                       &out_resp->count_props);
> -       if (ret)
> -               goto out;
> -
> -       if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
> -               copied = 0;
> -               encoder_ptr = (uint32_t __user *)(unsigned long)(out_resp->encoders_ptr);
> -               for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> -                       if (connector->encoder_ids[i] != 0) {
> -                               if (put_user(connector->encoder_ids[i],
> -                                            encoder_ptr + copied)) {
> -                                       ret = -EFAULT;
> -                                       goto out;
> -                               }
> -                               copied++;
> -                       }
> -               }
> -       }
> -       out_resp->count_encoders = encoders_count;
> -
> -out:
> -       drm_modeset_unlock(&dev->mode_config.connection_mutex);
> -
> -       drm_connector_unreference(connector);
> -out_unlock:
> -       mutex_unlock(&dev->mode_config.mutex);
> -
> -       return ret;
> -}
> -
>  static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
>  {
>         struct drm_connector *connector;
> @@ -3926,113 +3050,6 @@ err:
>         return ret;
>  }
>
> -/**
> - * drm_mode_connector_set_path_property - set tile property on connector
> - * @connector: connector to set property on.
> - * @path: path to use for property; must not be NULL.
> - *
> - * This creates a property to expose to userspace to specify a
> - * connector path. This is mainly used for DisplayPort MST where
> - * connectors have a topology and we want to allow userspace to give
> - * them more meaningful names.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_connector_set_path_property(struct drm_connector *connector,
> -                                        const char *path)
> -{
> -       struct drm_device *dev = connector->dev;
> -       int ret;
> -
> -       ret = drm_property_replace_global_blob(dev,
> -                                              &connector->path_blob_ptr,
> -                                              strlen(path) + 1,
> -                                              path,
> -                                              &connector->base,
> -                                              dev->mode_config.path_property);
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_mode_connector_set_path_property);
> -
> -/**
> - * drm_mode_connector_set_tile_property - set tile property on connector
> - * @connector: connector to set property on.
> - *
> - * This looks up the tile information for a connector, and creates a
> - * property for userspace to parse if it exists. The property is of
> - * the form of 8 integers using ':' as a separator.
> - *
> - * Returns:
> - * Zero on success, errno on failure.
> - */
> -int drm_mode_connector_set_tile_property(struct drm_connector *connector)
> -{
> -       struct drm_device *dev = connector->dev;
> -       char tile[256];
> -       int ret;
> -
> -       if (!connector->has_tile) {
> -               ret  = drm_property_replace_global_blob(dev,
> -                                                       &connector->tile_blob_ptr,
> -                                                       0,
> -                                                       NULL,
> -                                                       &connector->base,
> -                                                       dev->mode_config.tile_property);
> -               return ret;
> -       }
> -
> -       snprintf(tile, 256, "%d:%d:%d:%d:%d:%d:%d:%d",
> -                connector->tile_group->id, connector->tile_is_single_monitor,
> -                connector->num_h_tile, connector->num_v_tile,
> -                connector->tile_h_loc, connector->tile_v_loc,
> -                connector->tile_h_size, connector->tile_v_size);
> -
> -       ret = drm_property_replace_global_blob(dev,
> -                                              &connector->tile_blob_ptr,
> -                                              strlen(tile) + 1,
> -                                              tile,
> -                                              &connector->base,
> -                                              dev->mode_config.tile_property);
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_mode_connector_set_tile_property);
> -
> -/**
> - * drm_mode_connector_update_edid_property - update the edid property of a connector
> - * @connector: drm connector
> - * @edid: new value of the edid property
> - *
> - * This function creates a new blob modeset object and assigns its id to the
> - * connector's edid property.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_connector_update_edid_property(struct drm_connector *connector,
> -                                           const struct edid *edid)
> -{
> -       struct drm_device *dev = connector->dev;
> -       size_t size = 0;
> -       int ret;
> -
> -       /* ignore requests to set edid when overridden */
> -       if (connector->override_edid)
> -               return 0;
> -
> -       if (edid)
> -               size = EDID_LENGTH * (1 + edid->extensions);
> -
> -       ret = drm_property_replace_global_blob(dev,
> -                                              &connector->edid_blob_ptr,
> -                                              size,
> -                                              edid,
> -                                              &connector->base,
> -                                              dev->mode_config.edid_property);
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_mode_connector_update_edid_property);
> -
>  /* Some properties could refer to dynamic refcnt'd objects, or things that
>   * need special locking to handle lifetime issues (ie. to ensure the prop
>   * value doesn't become invalid part way through the property update due to
> @@ -4109,54 +3126,6 @@ void drm_property_change_valid_put(struct drm_property *property,
>                 drm_property_unreference_blob(obj_to_blob(ref));
>  }
>
> -/**
> - * drm_mode_connector_property_set_ioctl - set the current value of a connector property
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * This function sets the current value for a connectors's property. It also
> - * calls into a driver's ->set_property callback to update the hardware state
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
> -                                      void *data, struct drm_file *file_priv)
> -{
> -       struct drm_mode_connector_set_property *conn_set_prop = data;
> -       struct drm_mode_obj_set_property obj_set_prop = {
> -               .value = conn_set_prop->value,
> -               .prop_id = conn_set_prop->prop_id,
> -               .obj_id = conn_set_prop->connector_id,
> -               .obj_type = DRM_MODE_OBJECT_CONNECTOR
> -       };
> -
> -       /* It does all the locking and checking we need */
> -       return drm_mode_obj_set_property_ioctl(dev, &obj_set_prop, file_priv);
> -}
> -
> -static int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
> -                                          struct drm_property *property,
> -                                          uint64_t value)
> -{
> -       int ret = -EINVAL;
> -       struct drm_connector *connector = obj_to_connector(obj);
> -
> -       /* Do DPMS ourselves */
> -       if (property == connector->dev->mode_config.dpms_property) {
> -               ret = (*connector->funcs->dpms)(connector, (int)value);
> -       } else if (connector->funcs->set_property)
> -               ret = connector->funcs->set_property(connector, property, value);
> -
> -       /* store the property value if successful */
> -       if (!ret)
> -               drm_object_property_set_value(&connector->base, property, value);
> -       return ret;
> -}
> -
>  static int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
>                                       struct drm_property *property,
>                                       uint64_t value)
> @@ -4238,7 +3207,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
>                 goto out_unref;
>         }
>
> -       ret = get_properties(obj, file_priv->atomic,
> +       ret = drm_mode_object_get_properties(obj, file_priv->atomic,
>                         (uint32_t __user *)(unsigned long)(arg->props_ptr),
>                         (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
>                         &arg->count_props);
> @@ -4250,22 +3219,6 @@ out:
>         return ret;
>  }
>
> -/**
> - * drm_mode_obj_set_property_ioctl - set the current value of an object's property
> - * @dev: DRM device
> - * @data: ioctl data
> - * @file_priv: DRM file info
> - *
> - * This function sets the current value for an object's property. It also calls
> - * into a driver's ->set_property callback to update the hardware state.
> - * Compared to the connector specific ioctl this one is extended to also work on
> - * crtc and plane objects.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
>  int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
>                                     struct drm_file *file_priv)
>  {
> @@ -4331,47 +3284,6 @@ out:
>  }
>
>  /**
> - * drm_mode_connector_attach_encoder - attach a connector to an encoder
> - * @connector: connector to attach
> - * @encoder: encoder to attach @connector to
> - *
> - * This function links up a connector to an encoder. Note that the routing
> - * restrictions between encoders and crtcs are exposed to userspace through the
> - * possible_clones and possible_crtcs bitmasks.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_connector_attach_encoder(struct drm_connector *connector,
> -                                     struct drm_encoder *encoder)
> -{
> -       int i;
> -
> -       /*
> -        * In the past, drivers have attempted to model the static association
> -        * of connector to encoder in simple connector/encoder devices using a
> -        * direct assignment of connector->encoder = encoder. This connection
> -        * is a logical one and the responsibility of the core, so drivers are
> -        * expected not to mess with this.
> -        *
> -        * Note that the error return should've been enough here, but a large
> -        * majority of drivers ignores the return value, so add in a big WARN
> -        * to get people's attention.
> -        */
> -       if (WARN_ON(connector->encoder))
> -               return -EINVAL;
> -
> -       for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
> -               if (connector->encoder_ids[i] == 0) {
> -                       connector->encoder_ids[i] = encoder->base.id;
> -                       return 0;
> -               }
> -       }
> -       return -ENOMEM;
> -}
> -EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
> -
> -/**
>   * drm_mode_crtc_set_gamma_size - set the gamma table size
>   * @crtc: CRTC to set the gamma table size for
>   * @gamma_size: size of the gamma table
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index 5f1e9ff71ae4..7725d0fa7877 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -33,8 +33,6 @@
>
>
>  /* drm_crtc.c */
> -void drm_connector_ida_init(void);
> -void drm_connector_ida_destroy(void);
>  int drm_mode_object_get_reg(struct drm_device *dev,
>                             struct drm_mode_object *obj,
>                             uint32_t obj_type,
> @@ -48,6 +46,10 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
>                                                uint32_t id, uint32_t type);
>  void drm_mode_object_unregister(struct drm_device *dev,
>                                 struct drm_mode_object *object);
> +int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
> +                                  uint32_t __user *prop_ptr,
> +                                  uint64_t __user *prop_values,
> +                                  uint32_t *arg_count_props);
>  bool drm_property_change_valid_get(struct drm_property *property,
>                                    uint64_t value,
>                                    struct drm_mode_object **ref);
> @@ -85,8 +87,6 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
>                           struct drm_file *file_priv);
>  int drm_mode_getcrtc(struct drm_device *dev,
>                      void *data, struct drm_file *file_priv);
> -int drm_mode_getconnector(struct drm_device *dev,
> -                         void *data, struct drm_file *file_priv);
>  int drm_mode_setcrtc(struct drm_device *dev,
>                      void *data, struct drm_file *file_priv);
>  int drm_mode_getplane(struct drm_device *dev,
> @@ -105,8 +105,6 @@ int drm_mode_createblob_ioctl(struct drm_device *dev,
>                               void *data, struct drm_file *file_priv);
>  int drm_mode_destroyblob_ioctl(struct drm_device *dev,
>                                void *data, struct drm_file *file_priv);
> -int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
> -                                         void *data, struct drm_file *file_priv);
>  int drm_mode_getencoder(struct drm_device *dev,
>                         void *data, struct drm_file *file_priv);
>  int drm_mode_gamma_get_ioctl(struct drm_device *dev,
> @@ -117,6 +115,22 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
>  int drm_mode_page_flip_ioctl(struct drm_device *dev,
>                              void *data, struct drm_file *file_priv);
>
> +/* drm_connector.c */
> +void drm_connector_ida_init(void);
> +void drm_connector_ida_destroy(void);
> +void drm_connector_unregister_all(struct drm_device *dev);
> +int drm_connector_register_all(struct drm_device *dev);
> +int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj,
> +                                   struct drm_property *property,
> +                                   uint64_t value);
> +int drm_connector_create_standard_properties(struct drm_device *dev);
> +
> +/* IOCTL */
> +int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
> +                                         void *data, struct drm_file *file_priv);
> +int drm_mode_getconnector(struct drm_device *dev,
> +                         void *data, struct drm_file *file_priv);
> +
>  /* drm_framebuffer.c */
>  struct drm_framebuffer *
>  drm_internal_framebuffer_create(struct drm_device *dev,
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> new file mode 100644
> index 000000000000..ec2bea0b1b38
> --- /dev/null
> +++ b/include/drm/drm_connector.h
> @@ -0,0 +1,644 @@
> +/*
> + * Copyright (c) 2016 Intel Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission.  The copyright holders make no representations
> + * about the suitability of this software for any purpose.  It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#ifndef __DRM_CONNECTOR_H__
> +#define __DRM_CONNECTOR_H__
> +
> +#include <linux/list.h>
> +#include <linux/ctype.h>
> +#include <drm/drm_modeset.h>
> +
> +struct drm_connector_helper_funcs;
> +struct drm_device;
> +struct drm_crtc;
> +struct drm_encoder;
> +struct drm_property;
> +struct drm_property_blob;
> +struct edid;
> +
> +enum drm_connector_force {
> +       DRM_FORCE_UNSPECIFIED,
> +       DRM_FORCE_OFF,
> +       DRM_FORCE_ON,         /* force on analog part normally */
> +       DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
> +};
> +
> +enum drm_connector_status {
> +       connector_status_connected = 1,
> +       connector_status_disconnected = 2,
> +       connector_status_unknown = 3,
> +};
> +
> +enum subpixel_order {
> +       SubPixelUnknown = 0,
> +       SubPixelHorizontalRGB,
> +       SubPixelHorizontalBGR,
> +       SubPixelVerticalRGB,
> +       SubPixelVerticalBGR,
> +       SubPixelNone,
> +};
> +
> +/*
> + * Describes a given display (e.g. CRT or flat panel) and its limitations.
> + */
> +struct drm_display_info {
> +       char name[DRM_DISPLAY_INFO_LEN];
> +
> +       /* Physical size */
> +        unsigned int width_mm;
> +       unsigned int height_mm;
> +
> +       /* Clock limits FIXME: storage format */
> +       unsigned int min_vfreq, max_vfreq;
> +       unsigned int min_hfreq, max_hfreq;
> +       unsigned int pixel_clock;
> +       unsigned int bpc;
> +
> +       enum subpixel_order subpixel_order;
> +
> +#define DRM_COLOR_FORMAT_RGB444                (1<<0)
> +#define DRM_COLOR_FORMAT_YCRCB444      (1<<1)
> +#define DRM_COLOR_FORMAT_YCRCB422      (1<<2)
> +
> +       u32 color_formats;
> +
> +       const u32 *bus_formats;
> +       unsigned int num_bus_formats;
> +
> +#define DRM_BUS_FLAG_DE_LOW            (1<<0)
> +#define DRM_BUS_FLAG_DE_HIGH           (1<<1)
> +/* drive data on pos. edge */
> +#define DRM_BUS_FLAG_PIXDATA_POSEDGE   (1<<2)
> +/* drive data on neg. edge */
> +#define DRM_BUS_FLAG_PIXDATA_NEGEDGE   (1<<3)
> +
> +       u32 bus_flags;
> +
> +       /* Mask of supported hdmi deep color modes */
> +       u8 edid_hdmi_dc_modes;
> +
> +       u8 cea_rev;
> +};
> +
> +/**
> + * struct drm_connector_state - mutable connector state
> + * @connector: backpointer to the connector
> + * @crtc: CRTC to connect connector to, NULL if disabled
> + * @best_encoder: can be used by helpers and drivers to select the encoder
> + * @state: backpointer to global drm_atomic_state
> + */
> +struct drm_connector_state {
> +       struct drm_connector *connector;
> +
> +       struct drm_crtc *crtc;  /* do not write directly, use drm_atomic_set_crtc_for_connector() */
> +
> +       struct drm_encoder *best_encoder;
> +
> +       struct drm_atomic_state *state;
> +};
> +
> +/**
> + * struct drm_connector_funcs - control connectors on a given device
> + *
> + * Each CRTC may have one or more connectors attached to it.  The functions
> + * below allow the core DRM code to control connectors, enumerate available modes,
> + * etc.
> + */
> +struct drm_connector_funcs {
> +       /**
> +        * @dpms:
> +        *
> +        * Legacy entry point to set the per-connector DPMS state. Legacy DPMS
> +        * is exposed as a standard property on the connector, but diverted to
> +        * this callback in the drm core. Note that atomic drivers don't
> +        * implement the 4 level DPMS support on the connector any more, but
> +        * instead only have an on/off "ACTIVE" property on the CRTC object.
> +        *
> +        * Drivers implementing atomic modeset should use
> +        * drm_atomic_helper_connector_dpms() to implement this hook.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 on success or a negative error code on failure.
> +        */
> +       int (*dpms)(struct drm_connector *connector, int mode);
> +
> +       /**
> +        * @reset:
> +        *
> +        * Reset connector hardware and software state to off. This function isn't
> +        * called by the core directly, only through drm_mode_config_reset().
> +        * It's not a helper hook only for historical reasons.
> +        *
> +        * Atomic drivers can use drm_atomic_helper_connector_reset() to reset
> +        * atomic state using this hook.
> +        */
> +       void (*reset)(struct drm_connector *connector);
> +
> +       /**
> +        * @detect:
> +        *
> +        * Check to see if anything is attached to the connector. The parameter
> +        * force is set to false whilst polling, true when checking the
> +        * connector due to a user request. force can be used by the driver to
> +        * avoid expensive, destructive operations during automated probing.
> +        *
> +        * FIXME:
> +        *
> +        * Note that this hook is only called by the probe helper. It's not in
> +        * the helper library vtable purely for historical reasons. The only DRM
> +        * core entry point to probe connector state is @fill_modes.
> +        *
> +        * RETURNS:
> +        *
> +        * drm_connector_status indicating the connector's status.
> +        */
> +       enum drm_connector_status (*detect)(struct drm_connector *connector,
> +                                           bool force);
> +
> +       /**
> +        * @force:
> +        *
> +        * This function is called to update internal encoder state when the
> +        * connector is forced to a certain state by userspace, either through
> +        * the sysfs interfaces or on the kernel cmdline. In that case the
> +        * @detect callback isn't called.
> +        *
> +        * FIXME:
> +        *
> +        * Note that this hook is only called by the probe helper. It's not in
> +        * the helper library vtable purely for historical reasons. The only DRM
> +        * core entry point to probe connector state is @fill_modes.
> +        */
> +       void (*force)(struct drm_connector *connector);
> +
> +       /**
> +        * @fill_modes:
> +        *
> +        * Entry point for output detection and basic mode validation. The
> +        * driver should reprobe the output if needed (e.g. when hotplug
> +        * handling is unreliable), add all detected modes to connector->modes
> +        * and filter out any the device can't support in any configuration. It
> +        * also needs to filter out any modes wider or higher than the
> +        * parameters max_width and max_height indicate.
> +        *
> +        * The drivers must also prune any modes no longer valid from
> +        * connector->modes. Furthermore it must update connector->status and
> +        * connector->edid.  If no EDID has been received for this output
> +        * connector->edid must be NULL.
> +        *
> +        * Drivers using the probe helpers should use
> +        * drm_helper_probe_single_connector_modes() or
> +        * drm_helper_probe_single_connector_modes_nomerge() to implement this
> +        * function.
> +        *
> +        * RETURNS:
> +        *
> +        * The number of modes detected and filled into connector->modes.
> +        */
> +       int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
> +
> +       /**
> +        * @set_property:
> +        *
> +        * This is the legacy entry point to update a property attached to the
> +        * connector.
> +        *
> +        * Drivers implementing atomic modeset should use
> +        * drm_atomic_helper_connector_set_property() to implement this hook.
> +        *
> +        * This callback is optional if the driver does not support any legacy
> +        * driver-private properties.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 on success or a negative error code on failure.
> +        */
> +       int (*set_property)(struct drm_connector *connector, struct drm_property *property,
> +                            uint64_t val);
> +
> +       /**
> +        * @late_register:
> +        *
> +        * This optional hook can be used to register additional userspace
> +        * interfaces attached to the connector, light backlight control, i2c,
> +        * DP aux or similar interfaces. It is called late in the driver load
> +        * sequence from drm_connector_register() when registering all the
> +        * core drm connector interfaces. Everything added from this callback
> +        * should be unregistered in the early_unregister callback.
> +        *
> +        * Returns:
> +        *
> +        * 0 on success, or a negative error code on failure.
> +        */
> +       int (*late_register)(struct drm_connector *connector);
> +
> +       /**
> +        * @early_unregister:
> +        *
> +        * This optional hook should be used to unregister the additional
> +        * userspace interfaces attached to the connector from
> +        * late_unregister(). It is called from drm_connector_unregister(),
> +        * early in the driver unload sequence to disable userspace access
> +        * before data structures are torndown.
> +        */
> +       void (*early_unregister)(struct drm_connector *connector);
> +
> +       /**
> +        * @destroy:
> +        *
> +        * Clean up connector resources. This is called at driver unload time
> +        * through drm_mode_config_cleanup(). It can also be called at runtime
> +        * when a connector is being hot-unplugged for drivers that support
> +        * connector hotplugging (e.g. DisplayPort MST).
> +        */
> +       void (*destroy)(struct drm_connector *connector);
> +
> +       /**
> +        * @atomic_duplicate_state:
> +        *
> +        * Duplicate the current atomic state for this connector and return it.
> +        * The core and helpers gurantee that any atomic state duplicated with
> +        * this hook and still owned by the caller (i.e. not transferred to the
> +        * driver by calling ->atomic_commit() from struct
> +        * &drm_mode_config_funcs) will be cleaned up by calling the
> +        * @atomic_destroy_state hook in this structure.
> +        *
> +        * Atomic drivers which don't subclass struct &drm_connector_state should use
> +        * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
> +        * state structure to extend it with driver-private state should use
> +        * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
> +        * duplicated in a consistent fashion across drivers.
> +        *
> +        * It is an error to call this hook before connector->state has been
> +        * initialized correctly.
> +        *
> +        * NOTE:
> +        *
> +        * If the duplicate state references refcounted resources this hook must
> +        * acquire a reference for each of them. The driver must release these
> +        * references again in @atomic_destroy_state.
> +        *
> +        * RETURNS:
> +        *
> +        * Duplicated atomic state or NULL when the allocation failed.
> +        */
> +       struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
> +
> +       /**
> +        * @atomic_destroy_state:
> +        *
> +        * Destroy a state duplicated with @atomic_duplicate_state and release
> +        * or unreference all resources it references
> +        */
> +       void (*atomic_destroy_state)(struct drm_connector *connector,
> +                                    struct drm_connector_state *state);
> +
> +       /**
> +        * @atomic_set_property:
> +        *
> +        * Decode a driver-private property value and store the decoded value
> +        * into the passed-in state structure. Since the atomic core decodes all
> +        * standardized properties (even for extensions beyond the core set of
> +        * properties which might not be implemented by all drivers) this
> +        * requires drivers to subclass the state structure.
> +        *
> +        * Such driver-private properties should really only be implemented for
> +        * truly hardware/vendor specific state. Instead it is preferred to
> +        * standardize atomic extension and decode the properties used to expose
> +        * such an extension in the core.
> +        *
> +        * Do not call this function directly, use
> +        * drm_atomic_connector_set_property() instead.
> +        *
> +        * This callback is optional if the driver does not support any
> +        * driver-private atomic properties.
> +        *
> +        * NOTE:
> +        *
> +        * This function is called in the state assembly phase of atomic
> +        * modesets, which can be aborted for any reason (including on
> +        * userspace's request to just check whether a configuration would be
> +        * possible). Drivers MUST NOT touch any persistent state (hardware or
> +        * software) or data structures except the passed in @state parameter.
> +        *
> +        * Also since userspace controls in which order properties are set this
> +        * function must not do any input validation (since the state update is
> +        * incomplete and hence likely inconsistent). Instead any such input
> +        * validation must be done in the various atomic_check callbacks.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 if the property has been found, -EINVAL if the property isn't
> +        * implemented by the driver (which shouldn't ever happen, the core only
> +        * asks for properties attached to this connector). No other validation
> +        * is allowed by the driver. The core already checks that the property
> +        * value is within the range (integer, valid enum value, ...) the driver
> +        * set when registering the property.
> +        */
> +       int (*atomic_set_property)(struct drm_connector *connector,
> +                                  struct drm_connector_state *state,
> +                                  struct drm_property *property,
> +                                  uint64_t val);
> +
> +       /**
> +        * @atomic_get_property:
> +        *
> +        * Reads out the decoded driver-private property. This is used to
> +        * implement the GETCONNECTOR IOCTL.
> +        *
> +        * Do not call this function directly, use
> +        * drm_atomic_connector_get_property() instead.
> +        *
> +        * This callback is optional if the driver does not support any
> +        * driver-private atomic properties.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 on success, -EINVAL if the property isn't implemented by the
> +        * driver (which shouldn't ever happen, the core only asks for
> +        * properties attached to this connector).
> +        */
> +       int (*atomic_get_property)(struct drm_connector *connector,
> +                                  const struct drm_connector_state *state,
> +                                  struct drm_property *property,
> +                                  uint64_t *val);
> +};
> +
> +/* mode specified on the command line */
> +struct drm_cmdline_mode {
> +       bool specified;
> +       bool refresh_specified;
> +       bool bpp_specified;
> +       int xres, yres;
> +       int bpp;
> +       int refresh;
> +       bool rb;
> +       bool interlace;
> +       bool cvt;
> +       bool margins;
> +       enum drm_connector_force force;
> +};
> +
> +/**
> + * struct drm_connector - central DRM connector control structure
> + * @dev: parent DRM device
> + * @kdev: kernel device for sysfs attributes
> + * @attr: sysfs attributes
> + * @head: list management
> + * @base: base KMS object
> + * @name: human readable name, can be overwritten by the driver
> + * @connector_type: one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
> + * @connector_type_id: index into connector type enum
> + * @interlace_allowed: can this connector handle interlaced modes?
> + * @doublescan_allowed: can this connector handle doublescan?
> + * @stereo_allowed: can this connector handle stereo modes?
> + * @registered: is this connector exposed (registered) with userspace?
> + * @modes: modes available on this connector (from fill_modes() + user)
> + * @status: one of the drm_connector_status enums (connected, not, or unknown)
> + * @probed_modes: list of modes derived directly from the display
> + * @display_info: information about attached display (e.g. from EDID)
> + * @funcs: connector control functions
> + * @edid_blob_ptr: DRM property containing EDID if present
> + * @properties: property tracking for this connector
> + * @polled: a DRM_CONNECTOR_POLL_<foo> value for core driven polling
> + * @dpms: current dpms state
> + * @helper_private: mid-layer private data
> + * @cmdline_mode: mode line parsed from the kernel cmdline for this connector
> + * @force: a DRM_FORCE_<foo> state for forced mode sets
> + * @override_edid: has the EDID been overwritten through debugfs for testing?
> + * @encoder_ids: valid encoders for this connector
> + * @encoder: encoder driving this connector, if any
> + * @eld: EDID-like data, if present
> + * @dvi_dual: dual link DVI, if found
> + * @max_tmds_clock: max clock rate, if found
> + * @latency_present: AV delay info from ELD, if found
> + * @video_latency: video latency info from ELD, if found
> + * @audio_latency: audio latency info from ELD, if found
> + * @null_edid_counter: track sinks that give us all zeros for the EDID
> + * @bad_edid_counter: track sinks that give us an EDID with invalid checksum
> + * @edid_corrupt: indicates whether the last read EDID was corrupt
> + * @debugfs_entry: debugfs directory for this connector
> + * @state: current atomic state for this connector
> + * @has_tile: is this connector connected to a tiled monitor
> + * @tile_group: tile group for the connected monitor
> + * @tile_is_single_monitor: whether the tile is one monitor housing
> + * @num_h_tile: number of horizontal tiles in the tile group
> + * @num_v_tile: number of vertical tiles in the tile group
> + * @tile_h_loc: horizontal location of this tile
> + * @tile_v_loc: vertical location of this tile
> + * @tile_h_size: horizontal size of this tile.
> + * @tile_v_size: vertical size of this tile.
> + *
> + * Each connector may be connected to one or more CRTCs, or may be clonable by
> + * another connector if they can share a CRTC.  Each connector also has a specific
> + * position in the broader display (referred to as a 'screen' though it could
> + * span multiple monitors).
> + */
> +struct drm_connector {
> +       struct drm_device *dev;
> +       struct device *kdev;
> +       struct device_attribute *attr;
> +       struct list_head head;
> +
> +       struct drm_mode_object base;
> +
> +       char *name;
> +
> +       /**
> +        * @index: Compacted connector index, which matches the position inside
> +        * the mode_config.list for drivers not supporting hot-add/removing. Can
> +        * be used as an array index. It is invariant over the lifetime of the
> +        * connector.
> +        */
> +       unsigned index;
> +
> +       int connector_type;
> +       int connector_type_id;
> +       bool interlace_allowed;
> +       bool doublescan_allowed;
> +       bool stereo_allowed;
> +       bool registered;
> +       struct list_head modes; /* list of modes on this connector */
> +
> +       enum drm_connector_status status;
> +
> +       /* these are modes added by probing with DDC or the BIOS */
> +       struct list_head probed_modes;
> +
> +       struct drm_display_info display_info;
> +       const struct drm_connector_funcs *funcs;
> +
> +       struct drm_property_blob *edid_blob_ptr;
> +       struct drm_object_properties properties;
> +
> +       /**
> +        * @path_blob_ptr:
> +        *
> +        * DRM blob property data for the DP MST path property.
> +        */
> +       struct drm_property_blob *path_blob_ptr;
> +
> +       /**
> +        * @tile_blob_ptr:
> +        *
> +        * DRM blob property data for the tile property (used mostly by DP MST).
> +        * This is meant for screens which are driven through separate display
> +        * pipelines represented by &drm_crtc, which might not be running with
> +        * genlocked clocks. For tiled panels which are genlocked, like
> +        * dual-link LVDS or dual-link DSI, the driver should try to not expose
> +        * the tiling and virtualize both &drm_crtc and &drm_plane if needed.
> +        */
> +       struct drm_property_blob *tile_blob_ptr;
> +
> +/* should we poll this connector for connects and disconnects */
> +/* hot plug detectable */
> +#define DRM_CONNECTOR_POLL_HPD (1 << 0)
> +/* poll for connections */
> +#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
> +/* can cleanly poll for disconnections without flickering the screen */
> +/* DACs should rarely do this without a lot of testing */
> +#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
> +
> +       uint8_t polled; /* DRM_CONNECTOR_POLL_* */
> +
> +       /* requested DPMS state */
> +       int dpms;
> +
> +       const struct drm_connector_helper_funcs *helper_private;
> +
> +       /* forced on connector */
> +       struct drm_cmdline_mode cmdline_mode;
> +       enum drm_connector_force force;
> +       bool override_edid;
> +
> +#define DRM_CONNECTOR_MAX_ENCODER 3
> +       uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
> +       struct drm_encoder *encoder; /* currently active encoder */
> +
> +#define MAX_ELD_BYTES  128
> +       /* EDID bits */
> +       uint8_t eld[MAX_ELD_BYTES];
> +       bool dvi_dual;
> +       int max_tmds_clock;     /* in MHz */
> +       bool latency_present[2];
> +       int video_latency[2];   /* [0]: progressive, [1]: interlaced */
> +       int audio_latency[2];
> +       int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
> +       unsigned bad_edid_counter;
> +
> +       /* Flag for raw EDID header corruption - used in Displayport
> +        * compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
> +        */
> +       bool edid_corrupt;
> +
> +       struct dentry *debugfs_entry;
> +
> +       struct drm_connector_state *state;
> +
> +       /* DisplayID bits */
> +       bool has_tile;
> +       struct drm_tile_group *tile_group;
> +       bool tile_is_single_monitor;
> +
> +       uint8_t num_h_tile, num_v_tile;
> +       uint8_t tile_h_loc, tile_v_loc;
> +       uint16_t tile_h_size, tile_v_size;
> +};
> +
> +#define obj_to_connector(x) container_of(x, struct drm_connector, base)
> +
> +int drm_connector_init(struct drm_device *dev,
> +                      struct drm_connector *connector,
> +                      const struct drm_connector_funcs *funcs,
> +                      int connector_type);
> +int drm_connector_register(struct drm_connector *connector);
> +void drm_connector_unregister(struct drm_connector *connector);
> +int drm_mode_connector_attach_encoder(struct drm_connector *connector,
> +                                     struct drm_encoder *encoder);
> +
> +void drm_connector_cleanup(struct drm_connector *connector);
> +static inline unsigned drm_connector_index(struct drm_connector *connector)
> +{
> +       return connector->index;
> +}
> +
> +/**
> + * drm_connector_lookup - lookup connector object
> + * @dev: DRM device
> + * @id: connector object id
> + *
> + * This function looks up the connector object specified by id
> + * add takes a reference to it.
> + */
> +static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
> +               uint32_t id)
> +{
> +       struct drm_mode_object *mo;
> +       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
> +       return mo ? obj_to_connector(mo) : NULL;
> +}
> +
> +/**
> + * drm_connector_reference - incr the connector refcnt
> + * @connector: connector
> + *
> + * This function increments the connector's refcount.
> + */
> +static inline void drm_connector_reference(struct drm_connector *connector)
> +{
> +       drm_mode_object_reference(&connector->base);
> +}
> +
> +/**
> + * drm_connector_unreference - unref a connector
> + * @connector: connector to unref
> + *
> + * This function decrements the connector's refcount and frees it if it drops to zero.
> + */
> +static inline void drm_connector_unreference(struct drm_connector *connector)
> +{
> +       drm_mode_object_unreference(&connector->base);
> +}
> +
> +const char *drm_get_connector_status_name(enum drm_connector_status status);
> +const char *drm_get_subpixel_order_name(enum subpixel_order order);
> +const char *drm_get_dpms_name(int val);
> +const char *drm_get_dvi_i_subconnector_name(int val);
> +const char *drm_get_dvi_i_select_name(int val);
> +const char *drm_get_tv_subconnector_name(int val);
> +const char *drm_get_tv_select_name(int val);
> +
> +int drm_mode_create_dvi_i_properties(struct drm_device *dev);
> +int drm_mode_create_tv_properties(struct drm_device *dev,
> +                                 unsigned int num_modes,
> +                                 const char * const modes[]);
> +int drm_mode_create_scaling_mode_property(struct drm_device *dev);
> +int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
> +int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
> +
> +int drm_mode_connector_set_path_property(struct drm_connector *connector,
> +                                        const char *path);
> +int drm_mode_connector_set_tile_property(struct drm_connector *connector);
> +int drm_mode_connector_update_edid_property(struct drm_connector *connector,
> +                                           const struct edid *edid);
> +#endif
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 8b299b04079e..accae9ed6cd7 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -38,31 +38,16 @@
>  #include <drm/drm_modeset.h>
>  #include <drm/drm_framebuffer.h>
>  #include <drm/drm_modes.h>
> +#include <drm/drm_connector.h>
>
>  struct drm_device;
>  struct drm_mode_set;
> -struct drm_object_properties;
>  struct drm_file;
>  struct drm_clip_rect;
>  struct device_node;
>  struct fence;
>  struct edid;
>
> -#define DRM_OBJECT_MAX_PROPERTY 24
> -struct drm_object_properties {
> -       int count, atomic_count;
> -       /* NOTE: if we ever start dynamically destroying properties (ie.
> -        * not at drm_mode_config_cleanup() time), then we'd have to do
> -        * a better job of detaching property from mode objects to avoid
> -        * dangling property pointers:
> -        */
> -       struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
> -       /* do not read/write values directly, but use drm_object_property_get_value()
> -        * and drm_object_property_set_value():
> -        */
> -       uint64_t values[DRM_OBJECT_MAX_PROPERTY];
> -};
> -
>  static inline int64_t U642I64(uint64_t val)
>  {
>         return (int64_t)*((int64_t *)&val);
> @@ -86,61 +71,6 @@ static inline uint64_t I642U64(int64_t val)
>  #define DRM_REFLECT_X  4
>  #define DRM_REFLECT_Y  5
>
> -enum drm_connector_status {
> -       connector_status_connected = 1,
> -       connector_status_disconnected = 2,
> -       connector_status_unknown = 3,
> -};
> -
> -enum subpixel_order {
> -       SubPixelUnknown = 0,
> -       SubPixelHorizontalRGB,
> -       SubPixelHorizontalBGR,
> -       SubPixelVerticalRGB,
> -       SubPixelVerticalBGR,
> -       SubPixelNone,
> -};
> -
> -#define DRM_COLOR_FORMAT_RGB444                (1<<0)
> -#define DRM_COLOR_FORMAT_YCRCB444      (1<<1)
> -#define DRM_COLOR_FORMAT_YCRCB422      (1<<2)
> -
> -#define DRM_BUS_FLAG_DE_LOW            (1<<0)
> -#define DRM_BUS_FLAG_DE_HIGH           (1<<1)
> -/* drive data on pos. edge */
> -#define DRM_BUS_FLAG_PIXDATA_POSEDGE   (1<<2)
> -/* drive data on neg. edge */
> -#define DRM_BUS_FLAG_PIXDATA_NEGEDGE   (1<<3)
> -
> -/*
> - * Describes a given display (e.g. CRT or flat panel) and its limitations.
> - */
> -struct drm_display_info {
> -       char name[DRM_DISPLAY_INFO_LEN];
> -
> -       /* Physical size */
> -        unsigned int width_mm;
> -       unsigned int height_mm;
> -
> -       /* Clock limits FIXME: storage format */
> -       unsigned int min_vfreq, max_vfreq;
> -       unsigned int min_hfreq, max_hfreq;
> -       unsigned int pixel_clock;
> -       unsigned int bpc;
> -
> -       enum subpixel_order subpixel_order;
> -       u32 color_formats;
> -
> -       const u32 *bus_formats;
> -       unsigned int num_bus_formats;
> -       u32 bus_flags;
> -
> -       /* Mask of supported hdmi deep color modes */
> -       u8 edid_hdmi_dc_modes;
> -
> -       u8 cea_rev;
> -};
> -
>  /* data corresponds to displayid vend/prod/serial */
>  struct drm_tile_group {
>         struct kref refcount;
> @@ -177,7 +107,6 @@ struct drm_property {
>  };
>
>  struct drm_crtc;
> -struct drm_connector;
>  struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
> @@ -186,7 +115,6 @@ struct drm_atomic_state;
>
>  struct drm_crtc_helper_funcs;
>  struct drm_encoder_helper_funcs;
> -struct drm_connector_helper_funcs;
>  struct drm_plane_helper_funcs;
>
>  /**
> @@ -732,291 +660,6 @@ struct drm_crtc {
>  };
>
>  /**
> - * struct drm_connector_state - mutable connector state
> - * @connector: backpointer to the connector
> - * @crtc: CRTC to connect connector to, NULL if disabled
> - * @best_encoder: can be used by helpers and drivers to select the encoder
> - * @state: backpointer to global drm_atomic_state
> - */
> -struct drm_connector_state {
> -       struct drm_connector *connector;
> -
> -       struct drm_crtc *crtc;  /* do not write directly, use drm_atomic_set_crtc_for_connector() */
> -
> -       struct drm_encoder *best_encoder;
> -
> -       struct drm_atomic_state *state;
> -};
> -
> -/**
> - * struct drm_connector_funcs - control connectors on a given device
> - *
> - * Each CRTC may have one or more connectors attached to it.  The functions
> - * below allow the core DRM code to control connectors, enumerate available modes,
> - * etc.
> - */
> -struct drm_connector_funcs {
> -       /**
> -        * @dpms:
> -        *
> -        * Legacy entry point to set the per-connector DPMS state. Legacy DPMS
> -        * is exposed as a standard property on the connector, but diverted to
> -        * this callback in the drm core. Note that atomic drivers don't
> -        * implement the 4 level DPMS support on the connector any more, but
> -        * instead only have an on/off "ACTIVE" property on the CRTC object.
> -        *
> -        * Drivers implementing atomic modeset should use
> -        * drm_atomic_helper_connector_dpms() to implement this hook.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 on success or a negative error code on failure.
> -        */
> -       int (*dpms)(struct drm_connector *connector, int mode);
> -
> -       /**
> -        * @reset:
> -        *
> -        * Reset connector hardware and software state to off. This function isn't
> -        * called by the core directly, only through drm_mode_config_reset().
> -        * It's not a helper hook only for historical reasons.
> -        *
> -        * Atomic drivers can use drm_atomic_helper_connector_reset() to reset
> -        * atomic state using this hook.
> -        */
> -       void (*reset)(struct drm_connector *connector);
> -
> -       /**
> -        * @detect:
> -        *
> -        * Check to see if anything is attached to the connector. The parameter
> -        * force is set to false whilst polling, true when checking the
> -        * connector due to a user request. force can be used by the driver to
> -        * avoid expensive, destructive operations during automated probing.
> -        *
> -        * FIXME:
> -        *
> -        * Note that this hook is only called by the probe helper. It's not in
> -        * the helper library vtable purely for historical reasons. The only DRM
> -        * core entry point to probe connector state is @fill_modes.
> -        *
> -        * RETURNS:
> -        *
> -        * drm_connector_status indicating the connector's status.
> -        */
> -       enum drm_connector_status (*detect)(struct drm_connector *connector,
> -                                           bool force);
> -
> -       /**
> -        * @force:
> -        *
> -        * This function is called to update internal encoder state when the
> -        * connector is forced to a certain state by userspace, either through
> -        * the sysfs interfaces or on the kernel cmdline. In that case the
> -        * @detect callback isn't called.
> -        *
> -        * FIXME:
> -        *
> -        * Note that this hook is only called by the probe helper. It's not in
> -        * the helper library vtable purely for historical reasons. The only DRM
> -        * core entry point to probe connector state is @fill_modes.
> -        */
> -       void (*force)(struct drm_connector *connector);
> -
> -       /**
> -        * @fill_modes:
> -        *
> -        * Entry point for output detection and basic mode validation. The
> -        * driver should reprobe the output if needed (e.g. when hotplug
> -        * handling is unreliable), add all detected modes to connector->modes
> -        * and filter out any the device can't support in any configuration. It
> -        * also needs to filter out any modes wider or higher than the
> -        * parameters max_width and max_height indicate.
> -        *
> -        * The drivers must also prune any modes no longer valid from
> -        * connector->modes. Furthermore it must update connector->status and
> -        * connector->edid.  If no EDID has been received for this output
> -        * connector->edid must be NULL.
> -        *
> -        * Drivers using the probe helpers should use
> -        * drm_helper_probe_single_connector_modes() or
> -        * drm_helper_probe_single_connector_modes_nomerge() to implement this
> -        * function.
> -        *
> -        * RETURNS:
> -        *
> -        * The number of modes detected and filled into connector->modes.
> -        */
> -       int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
> -
> -       /**
> -        * @set_property:
> -        *
> -        * This is the legacy entry point to update a property attached to the
> -        * connector.
> -        *
> -        * Drivers implementing atomic modeset should use
> -        * drm_atomic_helper_connector_set_property() to implement this hook.
> -        *
> -        * This callback is optional if the driver does not support any legacy
> -        * driver-private properties.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 on success or a negative error code on failure.
> -        */
> -       int (*set_property)(struct drm_connector *connector, struct drm_property *property,
> -                            uint64_t val);
> -
> -       /**
> -        * @late_register:
> -        *
> -        * This optional hook can be used to register additional userspace
> -        * interfaces attached to the connector, light backlight control, i2c,
> -        * DP aux or similar interfaces. It is called late in the driver load
> -        * sequence from drm_connector_register() when registering all the
> -        * core drm connector interfaces. Everything added from this callback
> -        * should be unregistered in the early_unregister callback.
> -        *
> -        * Returns:
> -        *
> -        * 0 on success, or a negative error code on failure.
> -        */
> -       int (*late_register)(struct drm_connector *connector);
> -
> -       /**
> -        * @early_unregister:
> -        *
> -        * This optional hook should be used to unregister the additional
> -        * userspace interfaces attached to the connector from
> -        * late_unregister(). It is called from drm_connector_unregister(),
> -        * early in the driver unload sequence to disable userspace access
> -        * before data structures are torndown.
> -        */
> -       void (*early_unregister)(struct drm_connector *connector);
> -
> -       /**
> -        * @destroy:
> -        *
> -        * Clean up connector resources. This is called at driver unload time
> -        * through drm_mode_config_cleanup(). It can also be called at runtime
> -        * when a connector is being hot-unplugged for drivers that support
> -        * connector hotplugging (e.g. DisplayPort MST).
> -        */
> -       void (*destroy)(struct drm_connector *connector);
> -
> -       /**
> -        * @atomic_duplicate_state:
> -        *
> -        * Duplicate the current atomic state for this connector and return it.
> -        * The core and helpers gurantee that any atomic state duplicated with
> -        * this hook and still owned by the caller (i.e. not transferred to the
> -        * driver by calling ->atomic_commit() from struct
> -        * &drm_mode_config_funcs) will be cleaned up by calling the
> -        * @atomic_destroy_state hook in this structure.
> -        *
> -        * Atomic drivers which don't subclass struct &drm_connector_state should use
> -        * drm_atomic_helper_connector_duplicate_state(). Drivers that subclass the
> -        * state structure to extend it with driver-private state should use
> -        * __drm_atomic_helper_connector_duplicate_state() to make sure shared state is
> -        * duplicated in a consistent fashion across drivers.
> -        *
> -        * It is an error to call this hook before connector->state has been
> -        * initialized correctly.
> -        *
> -        * NOTE:
> -        *
> -        * If the duplicate state references refcounted resources this hook must
> -        * acquire a reference for each of them. The driver must release these
> -        * references again in @atomic_destroy_state.
> -        *
> -        * RETURNS:
> -        *
> -        * Duplicated atomic state or NULL when the allocation failed.
> -        */
> -       struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
> -
> -       /**
> -        * @atomic_destroy_state:
> -        *
> -        * Destroy a state duplicated with @atomic_duplicate_state and release
> -        * or unreference all resources it references
> -        */
> -       void (*atomic_destroy_state)(struct drm_connector *connector,
> -                                    struct drm_connector_state *state);
> -
> -       /**
> -        * @atomic_set_property:
> -        *
> -        * Decode a driver-private property value and store the decoded value
> -        * into the passed-in state structure. Since the atomic core decodes all
> -        * standardized properties (even for extensions beyond the core set of
> -        * properties which might not be implemented by all drivers) this
> -        * requires drivers to subclass the state structure.
> -        *
> -        * Such driver-private properties should really only be implemented for
> -        * truly hardware/vendor specific state. Instead it is preferred to
> -        * standardize atomic extension and decode the properties used to expose
> -        * such an extension in the core.
> -        *
> -        * Do not call this function directly, use
> -        * drm_atomic_connector_set_property() instead.
> -        *
> -        * This callback is optional if the driver does not support any
> -        * driver-private atomic properties.
> -        *
> -        * NOTE:
> -        *
> -        * This function is called in the state assembly phase of atomic
> -        * modesets, which can be aborted for any reason (including on
> -        * userspace's request to just check whether a configuration would be
> -        * possible). Drivers MUST NOT touch any persistent state (hardware or
> -        * software) or data structures except the passed in @state parameter.
> -        *
> -        * Also since userspace controls in which order properties are set this
> -        * function must not do any input validation (since the state update is
> -        * incomplete and hence likely inconsistent). Instead any such input
> -        * validation must be done in the various atomic_check callbacks.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 if the property has been found, -EINVAL if the property isn't
> -        * implemented by the driver (which shouldn't ever happen, the core only
> -        * asks for properties attached to this connector). No other validation
> -        * is allowed by the driver. The core already checks that the property
> -        * value is within the range (integer, valid enum value, ...) the driver
> -        * set when registering the property.
> -        */
> -       int (*atomic_set_property)(struct drm_connector *connector,
> -                                  struct drm_connector_state *state,
> -                                  struct drm_property *property,
> -                                  uint64_t val);
> -
> -       /**
> -        * @atomic_get_property:
> -        *
> -        * Reads out the decoded driver-private property. This is used to
> -        * implement the GETCONNECTOR IOCTL.
> -        *
> -        * Do not call this function directly, use
> -        * drm_atomic_connector_get_property() instead.
> -        *
> -        * This callback is optional if the driver does not support any
> -        * driver-private atomic properties.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 on success, -EINVAL if the property isn't implemented by the
> -        * driver (which shouldn't ever happen, the core only asks for
> -        * properties attached to this connector).
> -        */
> -       int (*atomic_get_property)(struct drm_connector *connector,
> -                                  const struct drm_connector_state *state,
> -                                  struct drm_property *property,
> -                                  uint64_t *val);
> -};
> -
> -/**
>   * struct drm_encoder_funcs - encoder controls
>   *
>   * Encoders sit between CRTCs and connectors.
> @@ -1067,8 +710,6 @@ struct drm_encoder_funcs {
>         void (*early_unregister)(struct drm_encoder *encoder);
>  };
>
> -#define DRM_CONNECTOR_MAX_ENCODER 3
> -
>  /**
>   * struct drm_encoder - central DRM encoder structure
>   * @dev: parent DRM device
> @@ -1109,171 +750,6 @@ struct drm_encoder {
>         const struct drm_encoder_helper_funcs *helper_private;
>  };
>
> -/* should we poll this connector for connects and disconnects */
> -/* hot plug detectable */
> -#define DRM_CONNECTOR_POLL_HPD (1 << 0)
> -/* poll for connections */
> -#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
> -/* can cleanly poll for disconnections without flickering the screen */
> -/* DACs should rarely do this without a lot of testing */
> -#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
> -
> -#define MAX_ELD_BYTES  128
> -
> -/**
> - * struct drm_connector - central DRM connector control structure
> - * @dev: parent DRM device
> - * @kdev: kernel device for sysfs attributes
> - * @attr: sysfs attributes
> - * @head: list management
> - * @base: base KMS object
> - * @name: human readable name, can be overwritten by the driver
> - * @connector_type: one of the DRM_MODE_CONNECTOR_<foo> types from drm_mode.h
> - * @connector_type_id: index into connector type enum
> - * @interlace_allowed: can this connector handle interlaced modes?
> - * @doublescan_allowed: can this connector handle doublescan?
> - * @stereo_allowed: can this connector handle stereo modes?
> - * @registered: is this connector exposed (registered) with userspace?
> - * @modes: modes available on this connector (from fill_modes() + user)
> - * @status: one of the drm_connector_status enums (connected, not, or unknown)
> - * @probed_modes: list of modes derived directly from the display
> - * @display_info: information about attached display (e.g. from EDID)
> - * @funcs: connector control functions
> - * @edid_blob_ptr: DRM property containing EDID if present
> - * @properties: property tracking for this connector
> - * @polled: a DRM_CONNECTOR_POLL_<foo> value for core driven polling
> - * @dpms: current dpms state
> - * @helper_private: mid-layer private data
> - * @cmdline_mode: mode line parsed from the kernel cmdline for this connector
> - * @force: a DRM_FORCE_<foo> state for forced mode sets
> - * @override_edid: has the EDID been overwritten through debugfs for testing?
> - * @encoder_ids: valid encoders for this connector
> - * @encoder: encoder driving this connector, if any
> - * @eld: EDID-like data, if present
> - * @dvi_dual: dual link DVI, if found
> - * @max_tmds_clock: max clock rate, if found
> - * @latency_present: AV delay info from ELD, if found
> - * @video_latency: video latency info from ELD, if found
> - * @audio_latency: audio latency info from ELD, if found
> - * @null_edid_counter: track sinks that give us all zeros for the EDID
> - * @bad_edid_counter: track sinks that give us an EDID with invalid checksum
> - * @edid_corrupt: indicates whether the last read EDID was corrupt
> - * @debugfs_entry: debugfs directory for this connector
> - * @state: current atomic state for this connector
> - * @has_tile: is this connector connected to a tiled monitor
> - * @tile_group: tile group for the connected monitor
> - * @tile_is_single_monitor: whether the tile is one monitor housing
> - * @num_h_tile: number of horizontal tiles in the tile group
> - * @num_v_tile: number of vertical tiles in the tile group
> - * @tile_h_loc: horizontal location of this tile
> - * @tile_v_loc: vertical location of this tile
> - * @tile_h_size: horizontal size of this tile.
> - * @tile_v_size: vertical size of this tile.
> - *
> - * Each connector may be connected to one or more CRTCs, or may be clonable by
> - * another connector if they can share a CRTC.  Each connector also has a specific
> - * position in the broader display (referred to as a 'screen' though it could
> - * span multiple monitors).
> - */
> -struct drm_connector {
> -       struct drm_device *dev;
> -       struct device *kdev;
> -       struct device_attribute *attr;
> -       struct list_head head;
> -
> -       struct drm_mode_object base;
> -
> -       char *name;
> -
> -       /**
> -        * @index: Compacted connector index, which matches the position inside
> -        * the mode_config.list for drivers not supporting hot-add/removing. Can
> -        * be used as an array index. It is invariant over the lifetime of the
> -        * connector.
> -        */
> -       unsigned index;
> -
> -       int connector_type;
> -       int connector_type_id;
> -       bool interlace_allowed;
> -       bool doublescan_allowed;
> -       bool stereo_allowed;
> -       bool registered;
> -       struct list_head modes; /* list of modes on this connector */
> -
> -       enum drm_connector_status status;
> -
> -       /* these are modes added by probing with DDC or the BIOS */
> -       struct list_head probed_modes;
> -
> -       struct drm_display_info display_info;
> -       const struct drm_connector_funcs *funcs;
> -
> -       struct drm_property_blob *edid_blob_ptr;
> -       struct drm_object_properties properties;
> -
> -       /**
> -        * @path_blob_ptr:
> -        *
> -        * DRM blob property data for the DP MST path property.
> -        */
> -       struct drm_property_blob *path_blob_ptr;
> -
> -       /**
> -        * @tile_blob_ptr:
> -        *
> -        * DRM blob property data for the tile property (used mostly by DP MST).
> -        * This is meant for screens which are driven through separate display
> -        * pipelines represented by &drm_crtc, which might not be running with
> -        * genlocked clocks. For tiled panels which are genlocked, like
> -        * dual-link LVDS or dual-link DSI, the driver should try to not expose
> -        * the tiling and virtualize both &drm_crtc and &drm_plane if needed.
> -        */
> -       struct drm_property_blob *tile_blob_ptr;
> -
> -       uint8_t polled; /* DRM_CONNECTOR_POLL_* */
> -
> -       /* requested DPMS state */
> -       int dpms;
> -
> -       const struct drm_connector_helper_funcs *helper_private;
> -
> -       /* forced on connector */
> -       struct drm_cmdline_mode cmdline_mode;
> -       enum drm_connector_force force;
> -       bool override_edid;
> -       uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
> -       struct drm_encoder *encoder; /* currently active encoder */
> -
> -       /* EDID bits */
> -       uint8_t eld[MAX_ELD_BYTES];
> -       bool dvi_dual;
> -       int max_tmds_clock;     /* in MHz */
> -       bool latency_present[2];
> -       int video_latency[2];   /* [0]: progressive, [1]: interlaced */
> -       int audio_latency[2];
> -       int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
> -       unsigned bad_edid_counter;
> -
> -       /* Flag for raw EDID header corruption - used in Displayport
> -        * compliance testing - * Displayport Link CTS Core 1.2 rev1.1 4.2.2.6
> -        */
> -       bool edid_corrupt;
> -
> -       struct dentry *debugfs_entry;
> -
> -       struct drm_connector_state *state;
> -
> -       /* DisplayID bits */
> -       bool has_tile;
> -       struct drm_tile_group *tile_group;
> -       bool tile_is_single_monitor;
> -
> -       uint8_t num_h_tile, num_v_tile;
> -       uint8_t tile_h_loc, tile_v_loc;
> -       uint16_t tile_h_size, tile_v_size;
> -};
> -
>  /**
>   * struct drm_plane_state - mutable plane state
>   * @plane: backpointer to the plane
> @@ -2601,7 +2077,6 @@ struct drm_mode_config {
>                 for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
>
>  #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
> -#define obj_to_connector(x) container_of(x, struct drm_connector, base)
>  #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
>  #define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
>  #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
> @@ -2647,19 +2122,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
>         return 1 << drm_crtc_index(crtc);
>  }
>
> -int drm_connector_init(struct drm_device *dev,
> -                      struct drm_connector *connector,
> -                      const struct drm_connector_funcs *funcs,
> -                      int connector_type);
> -int drm_connector_register(struct drm_connector *connector);
> -void drm_connector_unregister(struct drm_connector *connector);
> -
> -extern void drm_connector_cleanup(struct drm_connector *connector);
> -static inline unsigned drm_connector_index(struct drm_connector *connector)
> -{
> -       return connector->index;
> -}
> -
>  extern __printf(5, 6)
>  int drm_encoder_init(struct drm_device *dev,
>                      struct drm_encoder *encoder,
> @@ -2728,23 +2190,10 @@ extern int drm_crtc_force_disable_all(struct drm_device *dev);
>
>  extern void drm_encoder_cleanup(struct drm_encoder *encoder);
>
> -extern const char *drm_get_connector_status_name(enum drm_connector_status status);
> -extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
> -extern const char *drm_get_dpms_name(int val);
> -extern const char *drm_get_dvi_i_subconnector_name(int val);
> -extern const char *drm_get_dvi_i_select_name(int val);
> -extern const char *drm_get_tv_subconnector_name(int val);
> -extern const char *drm_get_tv_select_name(int val);
>  extern void drm_mode_config_init(struct drm_device *dev);
>  extern void drm_mode_config_reset(struct drm_device *dev);
>  extern void drm_mode_config_cleanup(struct drm_device *dev);
>
> -extern int drm_mode_connector_set_path_property(struct drm_connector *connector,
> -                                               const char *path);
> -int drm_mode_connector_set_tile_property(struct drm_connector *connector);
> -extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
> -                                                  const struct edid *edid);
> -
>  extern int drm_display_info_set_bus_formats(struct drm_display_info *info,
>                                             const u32 *formats,
>                                             unsigned int num_formats);
> @@ -2805,16 +2254,6 @@ void drm_property_unreference_blob(struct drm_property_blob *blob);
>  extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
>  extern int drm_property_add_enum(struct drm_property *property, int index,
>                                  uint64_t value, const char *name);
> -extern int drm_mode_create_dvi_i_properties(struct drm_device *dev);
> -extern int drm_mode_create_tv_properties(struct drm_device *dev,
> -                                        unsigned int num_modes,
> -                                        const char * const modes[]);
> -extern int drm_mode_create_scaling_mode_property(struct drm_device *dev);
> -extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
> -extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
> -
> -extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
> -                                            struct drm_encoder *encoder);
>  extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
>                                          int gamma_size);
>
> @@ -2874,22 +2313,6 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
>         return mo ? obj_to_encoder(mo) : NULL;
>  }
>
> -/**
> - * drm_connector_lookup - lookup connector object
> - * @dev: DRM device
> - * @id: connector object id
> - *
> - * This function looks up the connector object specified by id
> - * add takes a reference to it.
> - */
> -static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
> -               uint32_t id)
> -{
> -       struct drm_mode_object *mo;
> -       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
> -       return mo ? obj_to_connector(mo) : NULL;
> -}
> -
>  static inline struct drm_property *drm_property_find(struct drm_device *dev,
>                 uint32_t id)
>  {
> @@ -2917,28 +2340,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
>         return clamp_val(val, 0, max);
>  }
>
> -/**
> - * drm_connector_reference - incr the connector refcnt
> - * @connector: connector
> - *
> - * This function increments the connector's refcount.
> - */
> -static inline void drm_connector_reference(struct drm_connector *connector)
> -{
> -       drm_mode_object_reference(&connector->base);
> -}
> -
> -/**
> - * drm_connector_unreference - unref a connector
> - * @connector: connector to unref
> - *
> - * This function decrements the connector's refcount and frees it if it drops to zero.
> - */
> -static inline void drm_connector_unreference(struct drm_connector *connector)
> -{
> -       drm_mode_object_unreference(&connector->base);
> -}
> -
>  /* Plane list iterator for legacy (overlay only) planes. */
>  #define drm_for_each_legacy_plane(plane, dev) \
>         list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index f0af1edcbefe..efd291200a2b 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -28,6 +28,7 @@
>  #define __DRM_MODES_H__
>
>  #include <drm/drm_modeset.h>
> +#include <drm/drm_connector.h>
>
>  /*
>   * Note on terminology:  here, for brevity and convenience, we refer to connector
> @@ -402,21 +403,6 @@ struct drm_display_mode {
>         enum hdmi_picture_aspect picture_aspect_ratio;
>  };
>
> -/* mode specified on the command line */
> -struct drm_cmdline_mode {
> -       bool specified;
> -       bool refresh_specified;
> -       bool bpp_specified;
> -       int xres, yres;
> -       int bpp;
> -       int refresh;
> -       bool rb;
> -       bool interlace;
> -       bool cvt;
> -       bool margins;
> -       enum drm_connector_force force;
> -};
> -
>  /**
>   * drm_mode_is_stereo - check for stereo mode flags
>   * @mode: drm_display_mode to check
> diff --git a/include/drm/drm_modeset.h b/include/drm/drm_modeset.h
> index 0c2b0f3c5f34..fe910d5efe12 100644
> --- a/include/drm/drm_modeset.h
> +++ b/include/drm/drm_modeset.h
> @@ -25,6 +25,7 @@
>
>  #include <linux/kref.h>
>  struct drm_object_properties;
> +struct drm_property;
>
>  struct drm_mode_object {
>         uint32_t id;
> @@ -34,17 +35,36 @@ struct drm_mode_object {
>         void (*free_cb)(struct kref *kref);
>  };
>
> +#define DRM_OBJECT_MAX_PROPERTY 24
> +struct drm_object_properties {
> +       int count, atomic_count;
> +       /* NOTE: if we ever start dynamically destroying properties (ie.
> +        * not at drm_mode_config_cleanup() time), then we'd have to do
> +        * a better job of detaching property from mode objects to avoid
> +        * dangling property pointers:
> +        */
> +       struct drm_property *properties[DRM_OBJECT_MAX_PROPERTY];
> +       /* do not read/write values directly, but use drm_object_property_get_value()
> +        * and drm_object_property_set_value():
> +        */
> +       uint64_t values[DRM_OBJECT_MAX_PROPERTY];
> +};
> +
> +/* Avoid boilerplate.  I'm tired of typing. */
> +#define DRM_ENUM_NAME_FN(fnname, list)                         \
> +       const char *fnname(int val)                             \
> +       {                                                       \
> +               int i;                                          \
> +               for (i = 0; i < ARRAY_SIZE(list); i++) {        \
> +                       if (list[i].type == val)                \
> +                               return list[i].name;            \
> +               }                                               \
> +               return "(unknown)";                             \
> +       }
> +
>  struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
>                                              uint32_t id, uint32_t type);
>  void drm_mode_object_reference(struct drm_mode_object *obj);
>  void drm_mode_object_unreference(struct drm_mode_object *obj);
>
> -/* FIXME: This is temporary until we have a drm_connector.h */
> -enum drm_connector_force {
> -       DRM_FORCE_UNSPECIFIED,
> -       DRM_FORCE_OFF,
> -       DRM_FORCE_ON,         /* force on analog part normally */
> -       DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
> -};
> -
>  #endif
> --
> 2.8.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2016-08-10 15:06 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-09 13:41 [PATCH 00/20] more drm doc work Daniel Vetter
2016-08-09 13:41 ` [PATCH 01/20] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
2016-08-11  8:15   ` Jani Nikula
2016-08-11  8:23     ` Ville Syrjälä
2016-08-11  8:23     ` Jani Nikula
2016-08-11  9:29       ` Markus Heiser
2016-08-09 13:41 ` [PATCH 02/20] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
2016-08-09 16:19   ` Sean Paul
2016-08-09 13:41 ` [PATCH 03/20] drm/kms-helpers: Extract drm_modeset_helper.[hc] Daniel Vetter
2016-08-10 14:23   ` Sean Paul
2016-08-10 14:46     ` Daniel Vetter
2016-08-09 13:41 ` [PATCH 04/20] drm/doc: Reorg drm-mm.rst Daniel Vetter
2016-08-09 13:41 ` [PATCH 05/20] drm/doc: Reorg for drm-kms.rst Daniel Vetter
2016-08-09 13:41 ` [PATCH 06/20] drm/etnaviv: Don't set drm_device->platformdev Daniel Vetter
2016-08-09 13:41 ` [PATCH 07/20] drm/hisilicon: " Daniel Vetter
2016-08-09 13:41 ` [PATCH 08/20] drm/doc: Remove outdated FIXME for the page_flip callback Daniel Vetter
2016-08-09 13:41 ` [PATCH 09/20] drm/kms: Nuke dirty_info property Daniel Vetter
2016-08-09 13:59   ` Thomas Hellstrom
2016-08-09 14:08     ` Daniel Vetter
2016-08-10 12:07       ` Thomas Hellstrom
2016-08-09 13:41 ` [PATCH 10/20] drm/doc: Include drm_atomic.h Daniel Vetter
2016-08-09 13:41 ` [PATCH 11/20] drm: Extract drm_framebuffer.[hc] Daniel Vetter
2016-08-10 14:48   ` Sean Paul
2016-08-12 20:03     ` Daniel Vetter
2016-08-09 13:41 ` [PATCH 12/20] drm/doc: Update drm_framebuffer docs Daniel Vetter
2016-08-10 14:53   ` Sean Paul
2016-08-10 15:15   ` Ville Syrjälä
2016-08-12 20:09     ` Daniel Vetter
2016-08-09 13:41 ` [PATCH 13/20] drm: Export drm_property_replace_global_blob Daniel Vetter
2016-08-09 13:41 ` [PATCH 14/20] drm: Extract drm_connector.[hc] Daniel Vetter
2016-08-10 15:06   ` Sean Paul [this message]
2016-08-12 20:24     ` Daniel Vetter
2016-08-09 13:41 ` [PATCH 15/20] drm/doc: Include new drm_blend.c Daniel Vetter
2016-08-09 13:41 ` [PATCH 16/20] drm: Don't export dp-aux devnode functions Daniel Vetter
2016-08-10 15:09   ` [Intel-gfx] " Sean Paul
2016-08-09 13:41 ` [PATCH 17/20] drm: Update connector documentation Daniel Vetter
2016-08-10 15:14   ` Sean Paul
2016-08-09 13:41 ` [PATCH 18/20] drm: Remove display_info->min/max_(h|v)max Daniel Vetter
2016-08-09 13:41 ` [PATCH 19/20] drm: docume drm_display_info Daniel Vetter
2016-08-10 15:18   ` Sean Paul
2016-08-09 13:41 ` [PATCH 20/20] vgaarbiter: rst-ifiy and polish kerneldoc Daniel Vetter
2016-08-09 13:50   ` [PATCH] " Daniel Vetter
2016-08-10 15:27     ` Sean Paul
2016-08-09 13:50 ` ✗ Ro.CI.BAT: failure for more drm doc work Patchwork
2016-08-09 14:00 ` ✗ Ro.CI.BAT: failure for more drm doc work (rev2) Patchwork
2016-08-10  6:33 ` Patchwork
2016-08-10 15:04 ` ✗ Fi.CI.BAT: " Patchwork
2016-08-10 15:28 ` [PATCH 00/20] more drm doc work Sean Paul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CAOw6vbJv6D9o9beaiy-P_JvRa6GGAVLNgfG+8Dd26y3Ba-rwRQ@mail.gmail.com \
    --to=seanpaul@chromium.org \
    --cc=daniel.vetter@ffwll.ch \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.