All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings
@ 2016-08-12 20:48 Daniel Vetter
  2016-08-12 20:48 ` [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
                   ` (20 more replies)
  0 siblings, 21 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development
  Cc: Daniel Vetter, Markus Heiser, Jonathan Corbet, linux-doc, Daniel Vetter

These are the leftovers I could only track down using keep_warnings =
True. For some of them we might want to update our style guide on how
to reference structures and constants, not sure ...

Cc: Markus Heiser <markus.heiser@darmarit.de>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc.c              |  4 ++--
 drivers/gpu/drm/drm_fb_helper.c         |  2 +-
 drivers/gpu/drm/drm_irq.c               |  8 +++----
 drivers/gpu/drm/drm_simple_kms_helper.c |  2 +-
 drivers/gpu/drm/i915/i915_vgpu.c        | 42 ++++++++++++++++-----------------
 drivers/gpu/drm/i915/intel_audio.c      |  6 ++---
 drivers/gpu/drm/i915/intel_guc_fwif.h   |  5 ++--
 include/drm/drm_crtc.h                  |  8 +++----
 include/drm/drm_gem.h                   |  4 ++--
 9 files changed, 41 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index c31298f0bb0e..4cb8f4b49d8b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1272,7 +1272,7 @@ static unsigned int drm_num_planes(struct drm_device *dev)
  * @plane: plane object to init
  * @possible_crtcs: bitmask of possible CRTCs
  * @funcs: callbacks for the new plane
- * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
  * @type: type of plane (overlay, primary, cursor)
  * @name: printf style format string for the plane name, or NULL for default name
@@ -1387,7 +1387,7 @@ static void drm_plane_unregister_all(struct drm_device *dev)
  * @plane: plane object to init
  * @possible_crtcs: bitmask of possible CRTCs
  * @funcs: callbacks for the new plane
- * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
  * @is_primary: plane type (primary vs overlay)
  *
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index aed79d31930c..c0d1066ea419 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -2193,7 +2193,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
  * @fb_helper: the drm_fb_helper
  *
  * Scan the connectors attached to the fb_helper and try to put together a
- * setup after *notification of a change in output configuration.
+ * setup after notification of a change in output configuration.
  *
  * Called at runtime, takes the mode config locks to be able to check/change the
  * modeset configuration. Must be run from process context (which usually means
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 9bdce1cb6c5c..10611a936059 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -713,10 +713,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
  * Negative value on error, failure or if not supported in current
  * video mode:
  *
- * -EINVAL   - Invalid CRTC.
- * -EAGAIN   - Temporary unavailable, e.g., called before initial modeset.
- * -ENOTSUPP - Function not supported in current display mode.
- * -EIO      - Failed, e.g., due to failed scanout position query.
+ * -EINVAL    Invalid CRTC.
+ * -EAGAIN    Temporary unavailable, e.g., called before initial modeset.
+ * -ENOTSUPP  Function not supported in current display mode.
+ * -EIO       Failed, e.g., due to failed scanout position query.
  *
  * Returns or'ed positive status flags on success:
  *
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 0a02efe978ee..bada17166512 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -137,7 +137,7 @@ static const struct drm_plane_funcs drm_simple_kms_plane_funcs = {
  * @dev: DRM device
  * @pipe: simple display pipe object to initialize
  * @funcs: callbacks for the display pipe (optional)
- * @formats: array of supported formats (%DRM_FORMAT_*)
+ * @formats: array of supported formats (DRM_FORMAT\_\*)
  * @format_count: number of elements in @formats
  * @connector: connector to attach and register
  *
diff --git a/drivers/gpu/drm/i915/i915_vgpu.c b/drivers/gpu/drm/i915/i915_vgpu.c
index 142bac976919..ca2e91259948 100644
--- a/drivers/gpu/drm/i915/i915_vgpu.c
+++ b/drivers/gpu/drm/i915/i915_vgpu.c
@@ -156,27 +156,27 @@ static int vgt_balloon_space(struct drm_mm *mm,
  * host point of view, the graphic address space is partitioned by multiple
  * vGPUs in different VMs. ::
  *
- *                        vGPU1 view         Host view
- *             0 ------> +-----------+     +-----------+
- *               ^       |###########|     |   vGPU3   |
- *               |       |###########|     +-----------+
- *               |       |###########|     |   vGPU2   |
- *               |       +-----------+     +-----------+
- *        mappable GM    | available | ==> |   vGPU1   |
- *               |       +-----------+     +-----------+
- *               |       |###########|     |           |
- *               v       |###########|     |   Host    |
- *               +=======+===========+     +===========+
- *               ^       |###########|     |   vGPU3   |
- *               |       |###########|     +-----------+
- *               |       |###########|     |   vGPU2   |
- *               |       +-----------+     +-----------+
- *      unmappable GM    | available | ==> |   vGPU1   |
- *               |       +-----------+     +-----------+
- *               |       |###########|     |           |
- *               |       |###########|     |   Host    |
- *               v       |###########|     |           |
- * total GM size ------> +-----------+     +-----------+
+ *                         vGPU1 view         Host view
+ *              0 ------> +-----------+     +-----------+
+ *                ^       |###########|     |   vGPU3   |
+ *                |       |###########|     +-----------+
+ *                |       |###########|     |   vGPU2   |
+ *                |       +-----------+     +-----------+
+ *         mappable GM    | available | ==> |   vGPU1   |
+ *                |       +-----------+     +-----------+
+ *                |       |###########|     |           |
+ *                v       |###########|     |   Host    |
+ *                +=======+===========+     +===========+
+ *                ^       |###########|     |   vGPU3   |
+ *                |       |###########|     +-----------+
+ *                |       |###########|     |   vGPU2   |
+ *                |       +-----------+     +-----------+
+ *       unmappable GM    | available | ==> |   vGPU1   |
+ *                |       +-----------+     +-----------+
+ *                |       |###########|     |           |
+ *                |       |###########|     |   Host    |
+ *                v       |###########|     |           |
+ *  total GM size ------> +-----------+     +-----------+
  *
  * Returns:
  * zero on success, non-zero if configuration invalid or ballooning failed
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c
index d32f586f9c05..85389cdd0bec 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -51,10 +51,10 @@
  * related registers. (The notable exception is the power management, not
  * covered here.)
  *
- * The struct i915_audio_component is used to interact between the graphics
- * and audio drivers. The struct i915_audio_component_ops *ops in it is
+ * The struct &i915_audio_component is used to interact between the graphics
+ * and audio drivers. The struct &i915_audio_component_ops @ops in it is
  * defined in graphics driver and called in audio driver. The
- * struct i915_audio_component_audio_ops *audio_ops is called from i915 driver.
+ * struct &i915_audio_component_audio_ops @audio_ops is called from i915 driver.
  */
 
 static const struct {
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 944786d7075b..e40db2d2ae99 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -155,6 +155,7 @@
  *
  *     +-------------------------------+
  *     |        guc_css_header         |
+ *     |                               |
  *     | contains major/minor version  |
  *     +-------------------------------+
  *     |             uCode             |
@@ -176,10 +177,10 @@
  *
  * 1. Header, uCode and RSA are must-have components.
  * 2. All firmware components, if they present, are in the sequence illustrated
- * in the layout table above.
+ *    in the layout table above.
  * 3. Length info of each component can be found in header, in dwords.
  * 4. Modulus and exponent key are not required by driver. They may not appear
- * in fw. So driver will load a truncated firmware in this case.
+ *    in fw. So driver will load a truncated firmware in this case.
  */
 
 struct guc_css_header {
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index b618b506b04d..194eebb2f9d7 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1197,7 +1197,7 @@ struct drm_encoder_funcs {
  * @head: list management
  * @base: base KMS object
  * @name: human readable name, can be overwritten by the driver
- * @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h
+ * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
  * @possible_crtcs: bitmask of potential CRTC bindings
  * @possible_clones: bitmask of potential sibling encoders for cloning
  * @crtc: currently bound CRTC
@@ -1250,7 +1250,7 @@ struct drm_encoder {
  * @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: 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?
@@ -1263,11 +1263,11 @@ struct drm_encoder {
  * @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
+ * @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
+ * @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
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
index fca1cd1b9c26..9f63736e6163 100644
--- a/include/drm/drm_gem.h
+++ b/include/drm/drm_gem.h
@@ -210,8 +210,8 @@ drm_gem_object_reference(struct drm_gem_object *obj)
  * drm_gem_object_unreference_unlocked().
  *
  * Drivers should never call this directly in their code. Instead they should
- * wrap it up into a driver_gem_object_unreference(struct driver_gem_object
- * *obj) wrapper function, and use that. Shared code should never call this, to
+ * wrap it up into a ``driver_gem_object_unreference(struct driver_gem_object
+ * *obj)`` wrapper function, and use that. Shared code should never call this, to
  * avoid breaking drivers by accident which still depend upon dev->struct_mutex
  * locking.
  */
-- 
2.8.1


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc] Daniel Vetter
                   ` (19 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Move the common vtable stuff to the top
- Move "Tile Group" to a more appropriate heading level
- Throw away the old intro for the crtc helpers (it's entirely stale,
  e.g. helpers have become modular years ago), and replace it with a
  general intro about the motivation behind helpers.
- Reorder helpers to group them together a bit better, and explain
  that grouping in the intro.
- Make sure the introductory DOC section is always first.

v2:
- Remove bogus files accidentally added (Sean).
- Spelling fixes (Sean).

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms-helpers.rst | 208 +++++++++++++++++-----------------
 Documentation/gpu/drm-uapi.rst        |   3 +
 2 files changed, 107 insertions(+), 104 deletions(-)

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 0b302fedf1af..34f755bc9133 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -2,38 +2,45 @@
 Mode Setting Helper Functions
 =============================
 
-The plane, CRTC, encoder and connector functions provided by the drivers
-implement the DRM API. They're called by the DRM core and ioctl handlers
-to handle device state changes and configuration request. As
-implementing those functions often requires logic not specific to
-drivers, mid-layer helper functions are available to avoid duplicating
-boilerplate code.
-
-The DRM core contains one mid-layer implementation. The mid-layer
-provides implementations of several plane, CRTC, encoder and connector
-functions (called from the top of the mid-layer) that pre-process
-requests and call lower-level functions provided by the driver (at the
-bottom of the mid-layer). For instance, the
-:c:func:`drm_crtc_helper_set_config()` function can be used to
-fill the :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>`
-set_config field. When called, it will split the set_config operation
-in smaller, simpler operations and call the driver to handle them.
-
-To use the mid-layer, drivers call
-:c:func:`drm_crtc_helper_add()`,
-:c:func:`drm_encoder_helper_add()` and
-:c:func:`drm_connector_helper_add()` functions to install their
-mid-layer bottom operations handlers, and fill the :c:type:`struct
-drm_crtc_funcs <drm_crtc_funcs>`, :c:type:`struct
-drm_encoder_funcs <drm_encoder_funcs>` and :c:type:`struct
-drm_connector_funcs <drm_connector_funcs>` structures with
-pointers to the mid-layer top API functions. Installing the mid-layer
-bottom operation handlers is best done right after registering the
-corresponding KMS object.
-
-The mid-layer is not split between CRTC, encoder and connector
-operations. To use it, a driver must provide bottom functions for all of
-the three KMS entities.
+The DRM subsystem aims for a strong separation between core code and helper
+libraries. Core code takes care of general setup and teardown and decoding
+userspace requests to kernel internal objects. Everything else is handled by a
+large set of helper libraries, which can be combined freely to pick and choose
+for each driver what fits, and avoid shared code where special behaviour is
+needed.
+
+This distinction between core code and helpers is especially strong in the
+modesetting code, where there's a shared userspace ABI for all drivers. This is
+in contrast to the render side, where pretty much everything (with very few
+exceptions) can be considered optional helper code.
+
+There are a few areas these helpers can grouped into:
+
+* Helpers to implement modesetting. The important ones here are the atomic
+  helpers. Old drivers still often use the legacy CRTC helpers. They both share
+  the same set of common helper vtables. For really simple drivers (anything
+  that would have been a great fit in the deprecated fbdev subsystem) there's
+  also the simple display pipe helpers.
+
+* There's a big pile of helpers for handling outputs. First the generic bridge
+  helpers for handling encoder and transcoder IP blocks. Second the panel helpers
+  for handling panel-related information and logic. Plus then a big set of
+  helpers for the various sink standards (DisplayPort, HDMI, MIPI DSI). Finally
+  there's also generic helpers for handling output probing, and for dealing with
+  EDIDs.
+
+* The last group of helpers concerns itself with the frontend side of a display
+  pipeline: Planes, handling rectangles for visibility checking and scissoring,
+  flip queues and assorted bits.
+
+Modeset Helper Reference for Common Vtables
+===========================================
+
+.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
+   :internal:
+
+.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
+   :doc: overview
 
 Atomic Modeset Helper Functions Reference
 =========================================
@@ -62,33 +69,27 @@ Atomic State Reset and Initialization
 .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
    :export:
 
-Modeset Helper Reference for Common Vtables
-===========================================
-
-.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
-   :internal:
-
-.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
-   :doc: overview
-
 Legacy CRTC/Modeset Helper Functions Reference
 ==============================================
 
 .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
-   :export:
+   :doc: overview
 
 .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
-   :doc: overview
+   :export:
 
-Output Probing Helper Functions Reference
-=========================================
+Simple KMS Helper Reference
+===========================
 
-.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
-   :doc: output probing helper overview
+.. kernel-doc:: include/drm/drm_simple_kms_helper.h
+   :internal:
 
-.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
+.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
    :export:
 
+.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
+   :doc: overview
+
 fbdev Helper Functions Reference
 ================================
 
@@ -110,6 +111,36 @@ Framebuffer CMA Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
    :export:
 
+Bridges
+=======
+
+Overview
+--------
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+   :doc: overview
+
+Default bridge callback sequence
+--------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+   :doc: bridge callbacks
+
+.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+   :export:
+
+Panel Helper Reference
+======================
+
+.. kernel-doc:: include/drm/drm_panel.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_panel.c
+   :export:
+
+.. kernel-doc:: drivers/gpu/drm/drm_panel.c
+   :doc: drm panel
+
 Display Port Helper Functions Reference
 =======================================
 
@@ -158,6 +189,15 @@ MIPI DSI Helper Functions Reference
 .. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
    :export:
 
+Output Probing Helper Functions Reference
+=========================================
+
+.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
+   :doc: output probing helper overview
+
+.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
+   :export:
+
 EDID Helper Functions Reference
 ===============================
 
@@ -176,18 +216,6 @@ Rectangle Utilities Reference
 .. kernel-doc:: drivers/gpu/drm/drm_rect.c
    :export:
 
-Flip-work Helper Reference
-==========================
-
-.. kernel-doc:: include/drm/drm_flip_work.h
-   :doc: flip utils
-
-.. kernel-doc:: include/drm/drm_flip_work.h
-   :internal:
-
-.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
-   :export:
-
 HDMI Infoframes Helper Reference
 ================================
 
@@ -202,59 +230,31 @@ libraries and hence is also included here.
 .. kernel-doc:: drivers/video/hdmi.c
    :export:
 
-Plane Helper Reference
-======================
-
-.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
-   :export:
-
-.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
-   :doc: overview
-
-Tile group
-----------
-
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
-   :doc: Tile group
-
-Bridges
-=======
-
-Overview
---------
-
-.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
-   :doc: overview
+Flip-work Helper Reference
+==========================
 
-Default bridge callback sequence
---------------------------------
+.. kernel-doc:: include/drm/drm_flip_work.h
+   :doc: flip utils
 
-.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
-   :doc: bridge callbacks
+.. kernel-doc:: include/drm/drm_flip_work.h
+   :internal:
 
-.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
+.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
    :export:
 
-Panel Helper Reference
+Plane Helper Reference
 ======================
 
-.. kernel-doc:: include/drm/drm_panel.h
-   :internal:
+.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
+   :doc: overview
 
-.. kernel-doc:: drivers/gpu/drm/drm_panel.c
+.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
    :export:
 
-.. kernel-doc:: drivers/gpu/drm/drm_panel.c
-   :doc: drm panel
-
-Simple KMS Helper Reference
-===========================
-
-.. kernel-doc:: include/drm/drm_simple_kms_helper.h
-   :internal:
+Tile group
+==========
 
-.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
-   :export:
+# FIXME: This should probably be moved into a property documentation section
 
-.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
-   :doc: overview
+.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
+   :doc: Tile group
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 536bf3eaadd4..94876938aef3 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -33,6 +33,9 @@ Primary Nodes, DRM Master and Authentication
 .. kernel-doc:: include/drm/drm_auth.h
    :internal:
 
+Open-Source Userspace Requirements
+==================================
+
 Render nodes
 ============
 
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc]
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
  2016-08-12 20:48 ` [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 04/21] drm/doc: Reorg drm-mm.rst Daniel Vetter
                   ` (18 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

While reviewing docs I spotted that we have a few functions that
really just don't fit into their containing helper library section.
Extract them and shovel them all into a new library for random one-off
aux stuff.

v2: Remove wrongly added files for real.

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms-helpers.rst |   9 ++
 drivers/gpu/drm/Makefile              |   2 +-
 drivers/gpu/drm/drm_crtc_helper.c     |  56 -------------
 drivers/gpu/drm/drm_modeset_helper.c  | 153 ++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_plane_helper.c    |  66 ---------------
 include/drm/drm_atomic_helper.h       |   2 +
 include/drm/drm_crtc_helper.h         |   6 +-
 include/drm/drm_modeset_helper.h      |  36 ++++++++
 include/drm/drm_plane_helper.h        |   4 +-
 9 files changed, 203 insertions(+), 131 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_modeset_helper.c
 create mode 100644 include/drm/drm_modeset_helper.h

diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index 34f755bc9133..59fa3c11efab 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -258,3 +258,12 @@ Tile group
 
 .. kernel-doc:: drivers/gpu/drm/drm_crtc.c
    :doc: Tile group
+
+Auxiliary Modeset Helpers
+=========================
+
+.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
+   :doc: aux kms helpers
+
+.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
+   :export:
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0238bf8bc8c3..a5824d926dc9 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -24,7 +24,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
 		drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
-		drm_simple_kms_helper.o drm_blend.o
+		drm_simple_kms_helper.o drm_blend.o drm_modeset_helper.o
 
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 604d3ef72ffa..5d2cb138eba6 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -75,35 +75,6 @@
  */
 
 /**
- * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
- * 						connector list
- * @dev: drm device to operate on
- *
- * Some userspace presumes that the first connected connector is the main
- * display, where it's supposed to display e.g. the login screen. For
- * laptops, this should be the main panel. Use this function to sort all
- * (eDP/LVDS) panels to the front of the connector list, instead of
- * painstakingly trying to initialize them in the right order.
- */
-void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
-{
-	struct drm_connector *connector, *tmp;
-	struct list_head panel_list;
-
-	INIT_LIST_HEAD(&panel_list);
-
-	list_for_each_entry_safe(connector, tmp,
-				 &dev->mode_config.connector_list, head) {
-		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
-		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
-			list_move_tail(&connector->head, &panel_list);
-	}
-
-	list_splice(&panel_list, &dev->mode_config.connector_list);
-}
-EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
-
-/**
  * drm_helper_encoder_in_use - check if a given encoder is in use
  * @encoder: encoder to check
  *
@@ -913,33 +884,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
 EXPORT_SYMBOL(drm_helper_connector_dpms);
 
 /**
- * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
- * @fb: drm_framebuffer object to fill out
- * @mode_cmd: metadata from the userspace fb creation request
- *
- * This helper can be used in a drivers fb_create callback to pre-fill the fb's
- * metadata fields.
- */
-void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-				    const struct drm_mode_fb_cmd2 *mode_cmd)
-{
-	int i;
-
-	fb->width = mode_cmd->width;
-	fb->height = mode_cmd->height;
-	for (i = 0; i < 4; i++) {
-		fb->pitches[i] = mode_cmd->pitches[i];
-		fb->offsets[i] = mode_cmd->offsets[i];
-		fb->modifier[i] = mode_cmd->modifier[i];
-	}
-	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
-				    &fb->bits_per_pixel);
-	fb->pixel_format = mode_cmd->pixel_format;
-	fb->flags = mode_cmd->flags;
-}
-EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
-
-/**
  * drm_helper_resume_force_mode - force-restore mode setting configuration
  * @dev: drm_device which should be restored
  *
diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
new file mode 100644
index 000000000000..1d45738f8f98
--- /dev/null
+++ b/drivers/gpu/drm/drm_modeset_helper.c
@@ -0,0 +1,153 @@
+/*
+ * 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/drm_modeset_helper.h>
+#include <drm/drm_plane_helper.h>
+
+/**
+ * DOC: aux kms helpers
+ *
+ * This helper library contains various one-off functions which don't really fit
+ * anywhere else in the DRM modeset helper library.
+ */
+
+/**
+ * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
+ * 						connector list
+ * @dev: drm device to operate on
+ *
+ * Some userspace presumes that the first connected connector is the main
+ * display, where it's supposed to display e.g. the login screen. For
+ * laptops, this should be the main panel. Use this function to sort all
+ * (eDP/LVDS) panels to the front of the connector list, instead of
+ * painstakingly trying to initialize them in the right order.
+ */
+void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
+{
+	struct drm_connector *connector, *tmp;
+	struct list_head panel_list;
+
+	INIT_LIST_HEAD(&panel_list);
+
+	list_for_each_entry_safe(connector, tmp,
+				 &dev->mode_config.connector_list, head) {
+		if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+		    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+			list_move_tail(&connector->head, &panel_list);
+	}
+
+	list_splice(&panel_list, &dev->mode_config.connector_list);
+}
+EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
+
+/**
+ * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
+ * @fb: drm_framebuffer object to fill out
+ * @mode_cmd: metadata from the userspace fb creation request
+ *
+ * This helper can be used in a drivers fb_create callback to pre-fill the fb's
+ * metadata fields.
+ */
+void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+				    const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	int i;
+
+	fb->width = mode_cmd->width;
+	fb->height = mode_cmd->height;
+	for (i = 0; i < 4; i++) {
+		fb->pitches[i] = mode_cmd->pitches[i];
+		fb->offsets[i] = mode_cmd->offsets[i];
+		fb->modifier[i] = mode_cmd->modifier[i];
+	}
+	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
+				    &fb->bits_per_pixel);
+	fb->pixel_format = mode_cmd->pixel_format;
+	fb->flags = mode_cmd->flags;
+}
+EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
+
+/*
+ * This is the minimal list of formats that seem to be safe for modeset use
+ * with all current DRM drivers.  Most hardware can actually support more
+ * formats than this and drivers may specify a more accurate list when
+ * creating the primary plane.  However drivers that still call
+ * drm_plane_init() will use this minimal format list as the default.
+ */
+static const uint32_t safe_modeset_formats[] = {
+	DRM_FORMAT_XRGB8888,
+	DRM_FORMAT_ARGB8888,
+};
+
+static struct drm_plane *create_primary_plane(struct drm_device *dev)
+{
+	struct drm_plane *primary;
+	int ret;
+
+	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
+	if (primary == NULL) {
+		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
+		return NULL;
+	}
+
+	/*
+	 * Remove the format_default field from drm_plane when dropping
+	 * this helper.
+	 */
+	primary->format_default = true;
+
+	/* possible_crtc's will be filled in later by crtc_init */
+	ret = drm_universal_plane_init(dev, primary, 0,
+				       &drm_primary_helper_funcs,
+				       safe_modeset_formats,
+				       ARRAY_SIZE(safe_modeset_formats),
+				       DRM_PLANE_TYPE_PRIMARY, NULL);
+	if (ret) {
+		kfree(primary);
+		primary = NULL;
+	}
+
+	return primary;
+}
+
+/**
+ * drm_crtc_init - Legacy CRTC initialization function
+ * @dev: DRM device
+ * @crtc: CRTC object to init
+ * @funcs: callbacks for the new CRTC
+ *
+ * Initialize a CRTC object with a default helper-provided primary plane and no
+ * cursor plane.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+		  const struct drm_crtc_funcs *funcs)
+{
+	struct drm_plane *primary;
+
+	primary = create_primary_plane(dev);
+	return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
+					 NULL);
+}
+EXPORT_SYMBOL(drm_crtc_init);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index b522aabd1ab0..50b9c1bfc6f6 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -64,18 +64,6 @@
  */
 
 /*
- * This is the minimal list of formats that seem to be safe for modeset use
- * with all current DRM drivers.  Most hardware can actually support more
- * formats than this and drivers may specify a more accurate list when
- * creating the primary plane.  However drivers that still call
- * drm_plane_init() will use this minimal format list as the default.
- */
-static const uint32_t safe_modeset_formats[] = {
-	DRM_FORMAT_XRGB8888,
-	DRM_FORMAT_ARGB8888,
-};
-
-/*
  * Returns the connectors currently associated with a CRTC.  This function
  * should be called twice:  once with a NULL connector list to retrieve
  * the list size, and once with the properly allocated list to be filled in.
@@ -438,60 +426,6 @@ const struct drm_plane_funcs drm_primary_helper_funcs = {
 };
 EXPORT_SYMBOL(drm_primary_helper_funcs);
 
-static struct drm_plane *create_primary_plane(struct drm_device *dev)
-{
-	struct drm_plane *primary;
-	int ret;
-
-	primary = kzalloc(sizeof(*primary), GFP_KERNEL);
-	if (primary == NULL) {
-		DRM_DEBUG_KMS("Failed to allocate primary plane\n");
-		return NULL;
-	}
-
-	/*
-	 * Remove the format_default field from drm_plane when dropping
-	 * this helper.
-	 */
-	primary->format_default = true;
-
-	/* possible_crtc's will be filled in later by crtc_init */
-	ret = drm_universal_plane_init(dev, primary, 0,
-				       &drm_primary_helper_funcs,
-				       safe_modeset_formats,
-				       ARRAY_SIZE(safe_modeset_formats),
-				       DRM_PLANE_TYPE_PRIMARY, NULL);
-	if (ret) {
-		kfree(primary);
-		primary = NULL;
-	}
-
-	return primary;
-}
-
-/**
- * drm_crtc_init - Legacy CRTC initialization function
- * @dev: DRM device
- * @crtc: CRTC object to init
- * @funcs: callbacks for the new CRTC
- *
- * Initialize a CRTC object with a default helper-provided primary plane and no
- * cursor plane.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
-		  const struct drm_crtc_funcs *funcs)
-{
-	struct drm_plane *primary;
-
-	primary = create_primary_plane(dev);
-	return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
-					 NULL);
-}
-EXPORT_SYMBOL(drm_crtc_init);
-
 int drm_plane_helper_commit(struct drm_plane *plane,
 			    struct drm_plane_state *plane_state,
 			    struct drm_framebuffer *old_fb)
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index d86ae5dcd7b4..5a02e499f32b 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -29,6 +29,8 @@
 #define DRM_ATOMIC_HELPER_H_
 
 #include <drm/drm_crtc.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_modeset_helper.h>
 
 struct drm_atomic_state;
 
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 4b37afa2b73b..982c299e435a 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -41,6 +41,7 @@
 
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_modeset_helper.h>
 
 extern void drm_helper_disable_unused_functions(struct drm_device *dev);
 extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
@@ -53,11 +54,6 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
 
 extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
 
-extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
-
-extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-					   const struct drm_mode_fb_cmd2 *mode_cmd);
-
 extern void drm_helper_resume_force_mode(struct drm_device *dev);
 
 int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h
new file mode 100644
index 000000000000..b8051d5abe10
--- /dev/null
+++ b/include/drm/drm_modeset_helper.h
@@ -0,0 +1,36 @@
+/*
+ * 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_KMS_HELPER_H__
+#define __DRM_KMS_HELPER_H__
+
+#include <drm/drmP.h>
+
+void drm_helper_move_panel_connectors_to_head(struct drm_device *);
+
+void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
+				    const struct drm_mode_fb_cmd2 *mode_cmd);
+
+int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
+		  const struct drm_crtc_funcs *funcs);
+
+#endif
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index fbc8ecb3e5e8..c18959685c06 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -27,6 +27,7 @@
 #include <drm/drm_rect.h>
 #include <drm/drm_crtc.h>
 #include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_modeset_helper.h>
 
 /*
  * Drivers that don't allow primary plane scaling may pass this macro in place
@@ -37,9 +38,6 @@
  */
 #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
 
-int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
-		  const struct drm_crtc_funcs *funcs);
-
 int drm_plane_helper_check_state(struct drm_plane_state *state,
 				 const struct drm_rect *clip,
 				 int min_scale, int max_scale,
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/21] drm/doc: Reorg drm-mm.rst
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
  2016-08-12 20:48 ` [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
  2016-08-12 20:48 ` [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc] Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 05/21] drm/doc: Reorg for drm-kms.rst Daniel Vetter
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Readjust headings - we lost one level through the extraction into a
  separate .rst file.
- Merge helper reference sections with the helper documentation - that
  split was just an artifact of the docbook toolchain sucking at too
  deep nesting levels. No such problems with sphinx.
- Move the cma helpers in with the gem documentation, since they're
  helpers to implement gem using CMA/dma memory as a backend.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-mm.rst | 58 ++++++++++++++++++++++----------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst
index 59f9822fecd0..bca808535dfd 100644
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -26,12 +26,12 @@ TTM, but has no video RAM management capabilities and is thus limited to
 UMA devices.
 
 The Translation Table Manager (TTM)
------------------------------------
+===================================
 
 TTM design background and information belongs here.
 
 TTM initialization
-~~~~~~~~~~~~~~~~~~
+------------------
 
     **Warning**
 
@@ -77,7 +77,7 @@ object, ttm_global_item_ref() is used to create an initial reference
 count for the TTM, which will call your initialization function.
 
 The Graphics Execution Manager (GEM)
-------------------------------------
+====================================
 
 The GEM design approach has resulted in a memory manager that doesn't
 provide full coverage of all (or even all common) use cases in its
@@ -114,7 +114,7 @@ read & write, mapping, and domain ownership transfers are left to
 driver-specific ioctls.
 
 GEM Initialization
-~~~~~~~~~~~~~~~~~~
+------------------
 
 Drivers that use GEM must set the DRIVER_GEM bit in the struct
 :c:type:`struct drm_driver <drm_driver>` driver_features
@@ -132,7 +132,7 @@ typically not managed by GEM, and must be initialized separately into
 its own DRM MM object.
 
 GEM Objects Creation
-~~~~~~~~~~~~~~~~~~~~
+--------------------
 
 GEM splits creation of GEM objects and allocation of the memory that
 backs them in two distinct operations.
@@ -173,7 +173,7 @@ a call to :c:func:`drm_gem_private_object_init()` instead of
 must be managed by drivers.
 
 GEM Objects Lifetime
-~~~~~~~~~~~~~~~~~~~~
+--------------------
 
 All GEM objects are reference-counted by the GEM core. References can be
 acquired and release by :c:func:`calling
@@ -196,7 +196,7 @@ resources created by the GEM core, which need to be released with
 :c:func:`drm_gem_object_release()`.
 
 GEM Objects Naming
-~~~~~~~~~~~~~~~~~~
+------------------
 
 Communication between userspace and the kernel refers to GEM objects
 using local handles, global names or, more recently, file descriptors.
@@ -245,7 +245,7 @@ Furthermore PRIME also allows cross-device buffer sharing since it is
 based on dma-bufs.
 
 GEM Objects Mapping
-~~~~~~~~~~~~~~~~~~~
+-------------------
 
 Because mapping operations are fairly heavyweight GEM favours
 read/write-like access to buffers, implemented through driver-specific
@@ -304,7 +304,7 @@ Drivers that want to map the GEM object upfront instead of handling page
 faults can implement their own mmap file operation handler.
 
 Memory Coherency
-~~~~~~~~~~~~~~~~
+----------------
 
 When mapped to the device or used in a command buffer, backing pages for
 an object are flushed to memory and marked write combined so as to be
@@ -320,7 +320,7 @@ blocks the client and waits for rendering to complete before performing
 any necessary flushing operations).
 
 Command Execution
-~~~~~~~~~~~~~~~~~
+-----------------
 
 Perhaps the most important GEM function for GPU devices is providing a
 command execution interface to clients. Client programs construct
@@ -348,8 +348,20 @@ GEM Function Reference
 .. kernel-doc:: include/drm/drm_gem.h
    :internal:
 
+GEM CMA Helper Functions Reference
+----------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
+   :doc: cma helpers
+
+.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
+   :export:
+
+.. kernel-doc:: include/drm/drm_gem_cma_helper.h
+   :internal:
+
 VMA Offset Manager
-------------------
+==================
 
 .. kernel-doc:: drivers/gpu/drm/drm_vma_manager.c
    :doc: vma offset manager
@@ -361,14 +373,14 @@ VMA Offset Manager
    :internal:
 
 PRIME Buffer Sharing
---------------------
+====================
 
 PRIME is the cross device buffer sharing framework in drm, originally
 created for the OPTIMUS range of multi-gpu platforms. To userspace PRIME
 buffers are dma-buf based file descriptors.
 
 Overview and Driver Interface
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-----------------------------
 
 Similar to GEM global names, PRIME file descriptors are also used to
 share buffer objects across processes. They offer additional security:
@@ -406,7 +418,7 @@ struct drm_gem_object \*obj, int flags); struct drm_gem_object \*
 support PRIME.
 
 PRIME Helper Functions
-~~~~~~~~~~~~~~~~~~~~~~
+----------------------
 
 .. kernel-doc:: drivers/gpu/drm/drm_prime.c
    :doc: PRIME Helpers
@@ -418,16 +430,16 @@ PRIME Function References
    :export:
 
 DRM MM Range Allocator
-----------------------
+======================
 
 Overview
-~~~~~~~~
+--------
 
 .. kernel-doc:: drivers/gpu/drm/drm_mm.c
    :doc: Overview
 
 LRU Scan/Eviction Support
-~~~~~~~~~~~~~~~~~~~~~~~~~
+-------------------------
 
 .. kernel-doc:: drivers/gpu/drm/drm_mm.c
    :doc: lru scan roaster
@@ -440,15 +452,3 @@ DRM MM Range Allocator Function References
 
 .. kernel-doc:: include/drm/drm_mm.h
    :internal:
-
-CMA Helper Functions Reference
-------------------------------
-
-.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
-   :doc: cma helpers
-
-.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
-   :export:
-
-.. kernel-doc:: include/drm/drm_gem_cma_helper.h
-   :internal:
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/21] drm/doc: Reorg for drm-kms.rst
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (2 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 04/21] drm/doc: Reorg drm-mm.rst Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev Daniel Vetter
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Again adjust headings a bit, and don't mix up the initialization
  sections with other stuff.
- Remove the doc for output polling, that vfunc is now properly
  documented in the vfunc reference sections.
- Move the grab-bag with all the core stuff (i.e. drm_crtc.[hc]) to
  the front for a more prominent place.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst | 50 ++++++++++++++++---------------------------
 1 file changed, 19 insertions(+), 31 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 8dfa4b214b96..c92afa82b130 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -2,9 +2,6 @@
 Kernel Mode Setting (KMS)
 =========================
 
-Mode Setting
-============
-
 Drivers must initialize the mode setting core by calling
 :c:func:`drm_mode_config_init()` on the DRM device. The function
 initializes the :c:type:`struct drm_device <drm_device>`
@@ -18,17 +15,20 @@ be setup by initializing the following fields.
 -  struct drm_mode_config_funcs \*funcs;
    Mode setting functions.
 
-Display Modes Function Reference
---------------------------------
+KMS Data Structures
+===================
 
-.. kernel-doc:: include/drm/drm_modes.h
+.. kernel-doc:: include/drm/drm_crtc.h
    :internal:
 
-.. kernel-doc:: drivers/gpu/drm/drm_modes.c
+KMS API Functions
+=================
+
+.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
    :export:
 
 Atomic Mode Setting Function Reference
---------------------------------------
+======================================
 
 .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
    :export:
@@ -37,7 +37,7 @@ Atomic Mode Setting Function Reference
    :internal:
 
 Frame Buffer Abstraction
-------------------------
+========================
 
 Frame buffers are abstract memory objects that provide a source of
 pixels to scanout to a CRTC. Applications explicitly request the
@@ -65,13 +65,13 @@ drivers can manually clean up a framebuffer at module unload time with
 :c:func:`drm_framebuffer_unregister_private()`.
 
 DRM Format Handling
--------------------
+===================
 
 .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c
    :export:
 
 Dumb Buffer Objects
--------------------
+===================
 
 The KMS API doesn't standardize backing storage object creation and
 leaves it to driver-specific ioctls. Furthermore actually creating a
@@ -114,14 +114,14 @@ Note that dumb objects may not be used for gpu acceleration, as has been
 attempted on some ARM embedded platforms. Such drivers really must have
 a hardware-specific ioctl to allocate suitable buffer objects.
 
-Output Polling
---------------
+Display Modes Function Reference
+================================
+
+.. kernel-doc:: include/drm/drm_modes.h
+   :internal:
 
-void (\*output_poll_changed)(struct drm_device \*dev);
-This operation notifies the driver that the status of one or more
-connectors has changed. Drivers that use the fb helper can just call the
-:c:func:`drm_fb_helper_hotplug_event()` function to handle this
-operation.
+.. kernel-doc:: drivers/gpu/drm/drm_modes.c
+   :export:
 
 KMS Initialization and Cleanup
 ==============================
@@ -463,20 +463,8 @@ created for fetching EDID data and performing monitor detection. Once
 the process is complete, the new connector is registered with sysfs to
 make its properties available to applications.
 
-KMS API Functions
------------------
-
-.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
-   :export:
-
-KMS Data Structures
--------------------
-
-.. kernel-doc:: include/drm/drm_crtc.h
-   :internal:
-
 KMS Locking
------------
+===========
 
 .. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c
    :doc: kms locking
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (3 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 05/21] drm/doc: Reorg for drm-kms.rst Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15  9:07   ` Lucas Stach
  2016-08-12 20:48 ` [PATCH 07/21] drm/hisilicon: " Daniel Vetter
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter, Russell King

It's deprecated and only should be used by drivers which still use
drm_platform_init, not by anyone else.

And indeed it's entirely unused and can be nuked.

Cc: Lucas Stach <l.stach@pengutronix.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index ffd1b32caa8d..0c00947d15f2 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -533,8 +533,6 @@ static int etnaviv_bind(struct device *dev)
 	if (!drm)
 		return -ENOMEM;
 
-	drm->platformdev = to_platform_device(dev);
-
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv) {
 		dev_err(dev, "failed to allocate private data\n");
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/21] drm/hisilicon: Don't set drm_device->platformdev
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (4 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-17  3:19   ` Xinliang Liu
  2016-08-12 20:48 ` [PATCH 08/21] drm/doc: Remove outdated FIXME for the page_flip callback Daniel Vetter
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

It's deprecated and only should be used by drivers which still use
drm_platform_init, not by anyone else.

And indeed it's entirely unused and can be nuked.

This required a bit more fudging, but I guess kirin_dc_ops really
wants to operate on the platform_device, not something else. Also
bonus points for implementing abstraction, and then storing the vfunc
in a global variable.

Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
Cc: Archit Taneja <architt@codeaurora.org>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 10 +++++-----
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c |  6 ++----
 drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h |  4 ++--
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
index c3707d47cd89..34c22823e5c2 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
@@ -987,9 +987,9 @@ static int ade_dts_parse(struct platform_device *pdev, struct ade_hw_ctx *ctx)
 	return 0;
 }
 
-static int ade_drm_init(struct drm_device *dev)
+static int ade_drm_init(struct platform_device *pdev)
 {
-	struct platform_device *pdev = dev->platformdev;
+	struct drm_device *drm_dev = platform_get_drvdata(dev);
 	struct ade_data *ade;
 	struct ade_hw_ctx *ctx;
 	struct ade_crtc *acrtc;
@@ -1048,9 +1048,9 @@ static int ade_drm_init(struct drm_device *dev)
 	return 0;
 }
 
-static void ade_drm_cleanup(struct drm_device *dev)
+static void ade_drm_cleanup(struct platform_device *pdev)
 {
-	struct platform_device *pdev = dev->platformdev;
+	struct drm_device *drm_dev = platform_get_drvdata(dev);
 	struct ade_data *ade = platform_get_drvdata(pdev);
 	struct drm_crtc *crtc = &ade->acrtc.base;
 
@@ -1060,4 +1060,4 @@ static void ade_drm_cleanup(struct drm_device *dev)
 const struct kirin_dc_ops ade_dc_ops = {
 	.init = ade_drm_init,
 	.cleanup = ade_drm_cleanup
-};
+;
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 1edd9bc80294..a31016af9b61 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -41,7 +41,7 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev)
 #endif
 	drm_kms_helper_poll_fini(dev);
 	drm_vblank_cleanup(dev);
-	dc_ops->cleanup(dev);
+	dc_ops->cleanup(to_platform_device(dev->dev));
 	drm_mode_config_cleanup(dev);
 	devm_kfree(dev->dev, priv);
 	dev->dev_private = NULL;
@@ -103,7 +103,7 @@ static int kirin_drm_kms_init(struct drm_device *dev)
 	kirin_drm_mode_config_init(dev);
 
 	/* display controller init */
-	ret = dc_ops->init(dev);
+	ret = dc_ops->init(to_platform_device(dev));
 	if (ret)
 		goto err_mode_config_cleanup;
 
@@ -210,8 +210,6 @@ static int kirin_drm_bind(struct device *dev)
 	if (!drm_dev)
 		return -ENOMEM;
 
-	drm_dev->platformdev = to_platform_device(dev);
-
 	ret = kirin_drm_kms_init(drm_dev);
 	if (ret)
 		goto err_drm_dev_unref;
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
index 1a07caf8e7f4..a0bb217c4c64 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
@@ -15,8 +15,8 @@
 
 /* display controller init/cleanup ops */
 struct kirin_dc_ops {
-	int (*init)(struct drm_device *dev);
-	void (*cleanup)(struct drm_device *dev);
+	int (*init)(struct platform_device *pdev);
+	void (*cleanup)(struct platform_device *pdev);
 };
 
 struct kirin_drm_private {
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/21] drm/doc: Remove outdated FIXME for the page_flip callback
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (5 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 07/21] drm/hisilicon: " Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 09/21] drm/kms: Nuke dirty_info property Daniel Vetter
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

Since the drm_event cleanup work (as prep for fence support) drivers
don't need to bother themselves any more with this, the drm event core
takes care of that.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 include/drm/drm_crtc.h | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 194eebb2f9d7..410175be4c6a 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -547,16 +547,6 @@ struct drm_crtc_funcs {
 	 * counter and timestamp tracking though, e.g. if they have accurate
 	 * timestamp registers in hardware.
 	 *
-	 * FIXME:
-	 *
-	 * Up to that point drivers need to manage events themselves and can use
-	 * even->base.list freely for that. Specifically they need to ensure
-	 * that they don't send out page flip (or vblank) events for which the
-	 * corresponding drm file has been closed already. The drm core
-	 * unfortunately does not (yet) take care of that. Therefore drivers
-	 * currently must clean up and release pending events in their
-	 * ->preclose driver function.
-	 *
 	 * This callback is optional.
 	 *
 	 * NOTE:
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/21] drm/kms: Nuke dirty_info property
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (6 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 08/21] drm/doc: Remove outdated FIXME for the page_flip callback Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 10/21] drm/doc: Include drm_atomic.h Daniel Vetter
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development
  Cc: Jakob Bornecrantz, Daniel Vetter, Thomas Hellstrom, Dave Airlie,
	Daniel Vetter

It was added way back together with the dirty_fb ioctl, but neither
generic xfree86-modesetting nor the vmware driver use it. Everyone is
supposed to just unconditionally call the dirtyfb when they do
frontbuffer rendering.

And since unused uabi is bad uabi (there's reasons we require open
source userspace for everything) let's nuke this.

For reference see

commit 884840aa3ce3214259e69557be5b4ce0d781ffa4
Author: Jakob Bornecrantz <jakob@vmware.com>
Date:   Thu Dec 3 23:25:47 2009 +0000

    drm: Add dirty ioctl and property

Cc: Jakob Bornecrantz <jakob@vmware.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: Sinclair Yeh <syeh@vmware.com>
Cc: Thomas Hellstrom <thellstrom@vmware.com>
Acked-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc.c           | 31 -------------------------------
 drivers/gpu/drm/udl/udl_connector.c  |  3 ---
 drivers/gpu/drm/udl/udl_modeset.c    |  2 --
 drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c  |  9 ---------
 drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 11 -----------
 drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c |  7 -------
 include/drm/drm_crtc.h               |  7 -------
 7 files changed, 70 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 4cb8f4b49d8b..49cdac1f5a3d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -136,12 +136,6 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
-static const struct drm_prop_enum_list drm_dirty_info_enum_list[] = {
-	{ DRM_MODE_DIRTY_OFF,      "Off"      },
-	{ DRM_MODE_DIRTY_ON,       "On"       },
-	{ DRM_MODE_DIRTY_ANNOTATE, "Annotate" },
-};
-
 struct drm_conn_prop_enum_list {
 	int type;
 	const char *name;
@@ -1894,31 +1888,6 @@ int drm_mode_create_aspect_ratio_property(struct drm_device *dev)
 EXPORT_SYMBOL(drm_mode_create_aspect_ratio_property);
 
 /**
- * drm_mode_create_dirty_property - create dirty property
- * @dev: DRM device
- *
- * Called by a driver the first time it's needed, must be attached to desired
- * connectors.
- */
-int drm_mode_create_dirty_info_property(struct drm_device *dev)
-{
-	struct drm_property *dirty_info;
-
-	if (dev->mode_config.dirty_info_property)
-		return 0;
-
-	dirty_info =
-		drm_property_create_enum(dev, DRM_MODE_PROP_IMMUTABLE,
-				    "dirty",
-				    drm_dirty_info_enum_list,
-				    ARRAY_SIZE(drm_dirty_info_enum_list));
-	dev->mode_config.dirty_info_property = dirty_info;
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_mode_create_dirty_info_property);
-
-/**
  * drm_mode_create_suggested_offset_properties - create suggests offset properties
  * @dev: DRM device
  *
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index 4709b54c204c..d2f57c52f7db 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -150,8 +150,5 @@ int udl_connector_init(struct drm_device *dev, struct drm_encoder *encoder)
 	drm_connector_register(connector);
 	drm_mode_connector_attach_encoder(connector, encoder);
 
-	drm_object_attach_property(&connector->base,
-				      dev->mode_config.dirty_info_property,
-				      1);
 	return 0;
 }
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index f92ea9579674..73695127c573 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -441,8 +441,6 @@ int udl_modeset_init(struct drm_device *dev)
 
 	dev->mode_config.funcs = &udl_mode_funcs;
 
-	drm_mode_create_dirty_info_property(dev);
-
 	udl_crtc_init(dev);
 
 	encoder = udl_encoder_init(dev);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 63ccd9871ec9..23ec673d5e16 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -377,9 +377,6 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit)
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
-				   dev->mode_config.dirty_info_property,
-				   1);
-	drm_object_attach_property(&connector->base,
 				   dev_priv->hotplug_mode_update_property, 1);
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.suggested_x_property, 0);
@@ -421,10 +418,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
 	if (ret != 0)
 		goto err_free;
 
-	ret = drm_mode_create_dirty_info_property(dev);
-	if (ret != 0)
-		goto err_vblank_cleanup;
-
 	vmw_kms_create_implicit_placement_property(dev_priv, true);
 
 	if (dev_priv->capabilities & SVGA_CAP_MULTIMON)
@@ -439,8 +432,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
 
 	return 0;
 
-err_vblank_cleanup:
-	drm_vblank_cleanup(dev);
 err_free:
 	kfree(dev_priv->ldu_priv);
 	dev_priv->ldu_priv = NULL;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index b74eae2b8594..f42359084adc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -538,9 +538,6 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit)
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
-				   dev->mode_config.dirty_info_property,
-				   1);
-	drm_object_attach_property(&connector->base,
 				   dev_priv->hotplug_mode_update_property, 1);
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.suggested_x_property, 0);
@@ -574,10 +571,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = drm_mode_create_dirty_info_property(dev);
-	if (unlikely(ret != 0))
-		goto err_vblank_cleanup;
-
 	vmw_kms_create_implicit_placement_property(dev_priv, false);
 
 	for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
@@ -588,10 +581,6 @@ int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
 	DRM_INFO("Screen Objects Display Unit initialized\n");
 
 	return 0;
-
-err_vblank_cleanup:
-	drm_vblank_cleanup(dev);
-	return ret;
 }
 
 int vmw_kms_sou_close_display(struct vmw_private *dev_priv)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 41932a7c4f79..94ad8d2acf9a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -1131,9 +1131,6 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit)
 	drm_mode_crtc_set_gamma_size(crtc, 256);
 
 	drm_object_attach_property(&connector->base,
-				   dev->mode_config.dirty_info_property,
-				   1);
-	drm_object_attach_property(&connector->base,
 				   dev_priv->hotplug_mode_update_property, 1);
 	drm_object_attach_property(&connector->base,
 				   dev->mode_config.suggested_x_property, 0);
@@ -1202,10 +1199,6 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
 	if (unlikely(ret != 0))
 		return ret;
 
-	ret = drm_mode_create_dirty_info_property(dev);
-	if (unlikely(ret != 0))
-		goto err_vblank_cleanup;
-
 	dev_priv->active_display_unit = vmw_du_screen_target;
 
 	vmw_kms_create_implicit_placement_property(dev_priv, false);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 410175be4c6a..5a7809f029ba 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -2640,12 +2640,6 @@ struct drm_mode_config {
 	 */
 	struct drm_property *aspect_ratio_property;
 	/**
-	 * @dirty_info_property: Optional connector property to give userspace a
-	 * hint that the DIRTY_FB ioctl should be used.
-	 */
-	struct drm_property *dirty_info_property;
-
-	/**
 	 * @degamma_lut_property: Optional CRTC property to set the LUT used to
 	 * convert the framebuffer's colors to linear gamma.
 	 */
@@ -2943,7 +2937,6 @@ extern int drm_mode_create_tv_properties(struct drm_device *dev,
 					 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_dirty_info_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,
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/21] drm/doc: Include drm_atomic.h
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (7 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 09/21] drm/kms: Nuke dirty_info property Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 11/21] drm: Extract drm_framebuffer.[hc] Daniel Vetter
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

Accidentally the wrong file. Oops.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 Documentation/gpu/drm-kms.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index c92afa82b130..3ae4c12aca08 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -33,7 +33,7 @@ Atomic Mode Setting Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_atomic.c
    :export:
 
-.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
+.. kernel-doc:: include/drm/drm_atomic.h
    :internal:
 
 Frame Buffer Abstraction
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 11/21] drm: Extract drm_framebuffer.[hc]
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (8 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 10/21] drm/doc: Include drm_atomic.h Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 14:07   ` [PATCH] " Daniel Vetter
  2016-08-12 20:48 ` [PATCH 12/21] drm/doc: Update drm_framebuffer docs Daniel Vetter
                   ` (10 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

Also start with drm_modeset.h with the core bits, since we need
to untangle this mess somehow. That allows us to move the drm_modes.h
include to the right spot, except for the temporary connector status
enum. That will get fixed as soon as drm_connector.h exists.

v2: Rebase.

v3: Move drm_crtc_force_disable_all back again, that wasn't meant to
be moved (Sean).

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 Documentation/gpu/drm-kms.rst       |   9 +
 drivers/gpu/drm/Makefile            |   3 +-
 drivers/gpu/drm/drm_crtc.c          | 804 +-----------------------------------
 drivers/gpu/drm/drm_crtc_internal.h |  40 +-
 drivers/gpu/drm/drm_framebuffer.c   | 799 +++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h              | 162 +-------
 include/drm/drm_framebuffer.h       | 170 ++++++++
 include/drm/drm_modes.h             |   2 +
 include/drm/drm_modeset.h           |  50 +++
 9 files changed, 1078 insertions(+), 961 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_framebuffer.c
 create mode 100644 include/drm/drm_framebuffer.h
 create mode 100644 include/drm/drm_modeset.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 3ae4c12aca08..8264a88a8695 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -64,6 +64,15 @@ fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
 drivers can manually clean up a framebuffer at module unload time with
 :c:func:`drm_framebuffer_unregister_private()`.
 
+Frame Buffer Functions Reference
+--------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
+   :export:
+
+.. kernel-doc:: include/drm/drm_framebuffer.h
+   :internal:
+
 DRM Format Handling
 ===================
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a5824d926dc9..c71ec42ce511 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.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_modeset_lock.o drm_atomic.o drm_bridge.o \
+		drm_framebuffer.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_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 49cdac1f5a3d..daa1e54134ba 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -40,15 +40,11 @@
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_auth.h>
+#include <drm/drm_framebuffer.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
-static struct drm_framebuffer *
-internal_framebuffer_create(struct drm_device *dev,
-			    const struct drm_mode_fb_cmd2 *r,
-			    struct drm_file *file_priv);
-
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list)				\
 	const char *fnname(int val)				\
@@ -238,11 +234,11 @@ 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.
  */
-static int drm_mode_object_get_reg(struct drm_device *dev,
-				   struct drm_mode_object *obj,
-				   uint32_t obj_type,
-				   bool register_obj,
-				   void (*obj_free_cb)(struct kref *kref))
+int drm_mode_object_get_reg(struct drm_device *dev,
+			    struct drm_mode_object *obj,
+			    uint32_t obj_type,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref))
 {
 	int ret;
 
@@ -285,8 +281,8 @@ int drm_mode_object_get(struct drm_device *dev,
 	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
 }
 
-static void drm_mode_object_register(struct drm_device *dev,
-				     struct drm_mode_object *obj)
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj)
 {
 	mutex_lock(&dev->mode_config.idr_mutex);
 	idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
@@ -315,8 +311,8 @@ void drm_mode_object_unregister(struct drm_device *dev,
 	mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
-static struct drm_mode_object *_object_find(struct drm_device *dev,
-		uint32_t id, uint32_t type)
+struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
 {
 	struct drm_mode_object *obj = NULL;
 
@@ -351,7 +347,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 {
 	struct drm_mode_object *obj = NULL;
 
-	obj = _object_find(dev, id, type);
+	obj = __drm_mode_object_find(dev, id, type);
 	return obj;
 }
 EXPORT_SYMBOL(drm_mode_object_find);
@@ -435,205 +431,6 @@ out:
 }
 EXPORT_SYMBOL(drm_crtc_force_disable_all);
 
-static void drm_framebuffer_free(struct kref *kref)
-{
-	struct drm_framebuffer *fb =
-			container_of(kref, struct drm_framebuffer, base.refcount);
-	struct drm_device *dev = fb->dev;
-
-	/*
-	 * The lookup idr holds a weak reference, which has not necessarily been
-	 * removed at this point. Check for that.
-	 */
-	drm_mode_object_unregister(dev, &fb->base);
-
-	fb->funcs->destroy(fb);
-}
-
-/**
- * drm_framebuffer_init - initialize a framebuffer
- * @dev: DRM device
- * @fb: framebuffer to be initialized
- * @funcs: ... with these functions
- *
- * Allocates an ID for the framebuffer's parent mode object, sets its mode
- * functions & device file and adds it to the master fd list.
- *
- * IMPORTANT:
- * This functions publishes the fb and makes it available for concurrent access
- * by other users. Which means by this point the fb _must_ be fully set up -
- * since all the fb attributes are invariant over its lifetime, no further
- * locking but only correct reference counting is required.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
-			 const struct drm_framebuffer_funcs *funcs)
-{
-	int ret;
-
-	INIT_LIST_HEAD(&fb->filp_head);
-	fb->dev = dev;
-	fb->funcs = funcs;
-
-	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
-				      false, drm_framebuffer_free);
-	if (ret)
-		goto out;
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	dev->mode_config.num_fb++;
-	list_add(&fb->head, &dev->mode_config.fb_list);
-	mutex_unlock(&dev->mode_config.fb_lock);
-
-	drm_mode_object_register(dev, &fb->base);
-out:
-	return ret;
-}
-EXPORT_SYMBOL(drm_framebuffer_init);
-
-/**
- * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
- * @dev: drm device
- * @id: id of the fb object
- *
- * If successful, this grabs an additional reference to the framebuffer -
- * callers need to make sure to eventually unreference the returned framebuffer
- * again, using @drm_framebuffer_unreference.
- */
-struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
-					       uint32_t id)
-{
-	struct drm_mode_object *obj;
-	struct drm_framebuffer *fb = NULL;
-
-	obj = _object_find(dev, id, DRM_MODE_OBJECT_FB);
-	if (obj)
-		fb = obj_to_fb(obj);
-	return fb;
-}
-EXPORT_SYMBOL(drm_framebuffer_lookup);
-
-/**
- * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
- * @fb: fb to unregister
- *
- * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
- * those used for fbdev. Note that the caller must hold a reference of it's own,
- * i.e. the object may not be destroyed through this call (since it'll lead to a
- * locking inversion).
- */
-void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev;
-
-	if (!fb)
-		return;
-
-	dev = fb->dev;
-
-	/* Mark fb as reaped and drop idr ref. */
-	drm_mode_object_unregister(dev, &fb->base);
-}
-EXPORT_SYMBOL(drm_framebuffer_unregister_private);
-
-/**
- * drm_framebuffer_cleanup - remove a framebuffer object
- * @fb: framebuffer to remove
- *
- * Cleanup framebuffer. This function is intended to be used from the drivers
- * ->destroy callback. It can also be used to clean up driver private
- * framebuffers embedded into a larger structure.
- *
- * Note that this function does not remove the fb from active usuage - if it is
- * still used anywhere, hilarity can ensue since userspace could call getfb on
- * the id and get back -EINVAL. Obviously no concern at driver unload time.
- *
- * Also, the framebuffer will not be removed from the lookup idr - for
- * user-created framebuffers this will happen in in the rmfb ioctl. For
- * driver-private objects (e.g. for fbdev) drivers need to explicitly call
- * drm_framebuffer_unregister_private.
- */
-void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev = fb->dev;
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	list_del(&fb->head);
-	dev->mode_config.num_fb--;
-	mutex_unlock(&dev->mode_config.fb_lock);
-}
-EXPORT_SYMBOL(drm_framebuffer_cleanup);
-
-/**
- * drm_framebuffer_remove - remove and unreference a framebuffer object
- * @fb: framebuffer to remove
- *
- * Scans all the CRTCs and planes in @dev's mode_config.  If they're
- * using @fb, removes it, setting it to NULL. Then drops the reference to the
- * passed-in framebuffer. Might take the modeset locks.
- *
- * Note that this function optimizes the cleanup away if the caller holds the
- * last reference to the framebuffer. It is also guaranteed to not take the
- * modeset locks in this case.
- */
-void drm_framebuffer_remove(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev;
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
-
-	if (!fb)
-		return;
-
-	dev = fb->dev;
-
-	WARN_ON(!list_empty(&fb->filp_head));
-
-	/*
-	 * drm ABI mandates that we remove any deleted framebuffers from active
-	 * useage. But since most sane clients only remove framebuffers they no
-	 * longer need, try to optimize this away.
-	 *
-	 * Since we're holding a reference ourselves, observing a refcount of 1
-	 * means that we're the last holder and can skip it. Also, the refcount
-	 * can never increase from 1 again, so we don't need any barriers or
-	 * locks.
-	 *
-	 * Note that userspace could try to race with use and instate a new
-	 * usage _after_ we've cleared all current ones. End result will be an
-	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
-	 * in this manner.
-	 */
-	if (drm_framebuffer_read_refcount(fb) > 1) {
-		if (dev->mode_config.funcs->atomic_commit) {
-			drm_atomic_remove_fb(fb);
-			goto out;
-		}
-
-		drm_modeset_lock_all(dev);
-		/* remove from any CRTC */
-		drm_for_each_crtc(crtc, dev) {
-			if (crtc->primary->fb == fb) {
-				/* should turn off the crtc */
-				if (drm_crtc_force_disable(crtc))
-					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
-			}
-		}
-
-		drm_for_each_plane(plane, dev) {
-			if (plane->fb == fb)
-				drm_plane_force_disable(plane);
-		}
-		drm_modeset_unlock_all(dev);
-	}
-
-out:
-	drm_framebuffer_unreference(fb);
-}
-EXPORT_SYMBOL(drm_framebuffer_remove);
-
 DEFINE_WW_CLASS(crtc_ww_class);
 
 static unsigned int drm_num_crtcs(struct drm_device *dev)
@@ -3010,7 +2807,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 	 */
 	if (req->flags & DRM_MODE_CURSOR_BO) {
 		if (req->handle) {
-			fb = internal_framebuffer_create(dev, &fbreq, file_priv);
+			fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
 			if (IS_ERR(fb)) {
 				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
 				return PTR_ERR(fb);
@@ -3208,578 +3005,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
 }
 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 
-/**
- * drm_mode_addfb - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request. This is the
- * original addfb ioctl which only supported RGB formats.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_addfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd *or = data;
-	struct drm_mode_fb_cmd2 r = {};
-	int ret;
-
-	/* convert to new format and call new ioctl */
-	r.fb_id = or->fb_id;
-	r.width = or->width;
-	r.height = or->height;
-	r.pitches[0] = or->pitch;
-	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
-	r.handles[0] = or->handle;
-
-	ret = drm_mode_addfb2(dev, &r, file_priv);
-	if (ret)
-		return ret;
-
-	or->fb_id = r.fb_id;
-
-	return 0;
-}
-
-static int format_check(const struct drm_mode_fb_cmd2 *r)
-{
-	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB332:
-	case DRM_FORMAT_BGR233:
-	case DRM_FORMAT_XRGB4444:
-	case DRM_FORMAT_XBGR4444:
-	case DRM_FORMAT_RGBX4444:
-	case DRM_FORMAT_BGRX4444:
-	case DRM_FORMAT_ARGB4444:
-	case DRM_FORMAT_ABGR4444:
-	case DRM_FORMAT_RGBA4444:
-	case DRM_FORMAT_BGRA4444:
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XBGR1555:
-	case DRM_FORMAT_RGBX5551:
-	case DRM_FORMAT_BGRX5551:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_ABGR1555:
-	case DRM_FORMAT_RGBA5551:
-	case DRM_FORMAT_BGRA5551:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_BGR565:
-	case DRM_FORMAT_RGB888:
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_RGBX8888:
-	case DRM_FORMAT_BGRX8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_RGBA8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_BGRA1010102:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_AYUV:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_NV24:
-	case DRM_FORMAT_NV42:
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV444:
-	case DRM_FORMAT_YVU444:
-		return 0;
-	default:
-		DRM_DEBUG_KMS("invalid pixel format %s\n",
-			      drm_get_format_name(r->pixel_format));
-		return -EINVAL;
-	}
-}
-
-static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
-{
-	int ret, hsub, vsub, num_planes, i;
-
-	ret = format_check(r);
-	if (ret) {
-		DRM_DEBUG_KMS("bad framebuffer format %s\n",
-			      drm_get_format_name(r->pixel_format));
-		return ret;
-	}
-
-	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
-	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
-	num_planes = drm_format_num_planes(r->pixel_format);
-
-	if (r->width == 0 || r->width % hsub) {
-		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
-		return -EINVAL;
-	}
-
-	if (r->height == 0 || r->height % vsub) {
-		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < num_planes; i++) {
-		unsigned int width = r->width / (i != 0 ? hsub : 1);
-		unsigned int height = r->height / (i != 0 ? vsub : 1);
-		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
-
-		if (!r->handles[i]) {
-			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if ((uint64_t) width * cpp > UINT_MAX)
-			return -ERANGE;
-
-		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
-			return -ERANGE;
-
-		if (r->pitches[i] < width * cpp) {
-			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
-			return -EINVAL;
-		}
-
-		if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
-			DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
-				      r->modifier[i], i);
-			return -EINVAL;
-		}
-
-		/* modifier specific checks: */
-		switch (r->modifier[i]) {
-		case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
-			/* NOTE: the pitch restriction may be lifted later if it turns
-			 * out that no hw has this restriction:
-			 */
-			if (r->pixel_format != DRM_FORMAT_NV12 ||
-					width % 128 || height % 32 ||
-					r->pitches[i] % 128) {
-				DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
-				return -EINVAL;
-			}
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	for (i = num_planes; i < 4; i++) {
-		if (r->modifier[i]) {
-			DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
-		if (!(r->flags & DRM_MODE_FB_MODIFIERS))
-			continue;
-
-		if (r->handles[i]) {
-			DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if (r->pitches[i]) {
-			DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if (r->offsets[i]) {
-			DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static struct drm_framebuffer *
-internal_framebuffer_create(struct drm_device *dev,
-			    const struct drm_mode_fb_cmd2 *r,
-			    struct drm_file *file_priv)
-{
-	struct drm_mode_config *config = &dev->mode_config;
-	struct drm_framebuffer *fb;
-	int ret;
-
-	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
-		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if ((config->min_width > r->width) || (r->width > config->max_width)) {
-		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
-			  r->width, config->min_width, config->max_width);
-		return ERR_PTR(-EINVAL);
-	}
-	if ((config->min_height > r->height) || (r->height > config->max_height)) {
-		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
-			  r->height, config->min_height, config->max_height);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (r->flags & DRM_MODE_FB_MODIFIERS &&
-	    !dev->mode_config.allow_fb_modifiers) {
-		DRM_DEBUG_KMS("driver does not support fb modifiers\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	ret = framebuffer_check(r);
-	if (ret)
-		return ERR_PTR(ret);
-
-	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
-	if (IS_ERR(fb)) {
-		DRM_DEBUG_KMS("could not create framebuffer\n");
-		return fb;
-	}
-
-	return fb;
-}
-
-/**
- * drm_mode_addfb2 - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request with format. This is
- * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
- * and uses fourcc codes as pixel format specifiers.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_addfb2(struct drm_device *dev,
-		    void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd2 *r = data;
-	struct drm_framebuffer *fb;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = internal_framebuffer_create(dev, r, file_priv);
-	if (IS_ERR(fb))
-		return PTR_ERR(fb);
-
-	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
-	r->fb_id = fb->base.id;
-
-	/* Transfer ownership to the filp for reaping on close */
-	mutex_lock(&file_priv->fbs_lock);
-	list_add(&fb->filp_head, &file_priv->fbs);
-	mutex_unlock(&file_priv->fbs_lock);
-
-	return 0;
-}
-
-struct drm_mode_rmfb_work {
-	struct work_struct work;
-	struct list_head fbs;
-};
-
-static void drm_mode_rmfb_work_fn(struct work_struct *w)
-{
-	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
-
-	while (!list_empty(&arg->fbs)) {
-		struct drm_framebuffer *fb =
-			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
-
-		list_del_init(&fb->filp_head);
-		drm_framebuffer_remove(fb);
-	}
-}
-
-/**
- * drm_mode_rmfb - remove an FB from the configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Remove the FB specified by the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_rmfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_framebuffer *fb = NULL;
-	struct drm_framebuffer *fbl = NULL;
-	uint32_t *id = data;
-	int found = 0;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, *id);
-	if (!fb)
-		return -ENOENT;
-
-	mutex_lock(&file_priv->fbs_lock);
-	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
-		if (fb == fbl)
-			found = 1;
-	if (!found) {
-		mutex_unlock(&file_priv->fbs_lock);
-		goto fail_unref;
-	}
-
-	list_del_init(&fb->filp_head);
-	mutex_unlock(&file_priv->fbs_lock);
-
-	/* drop the reference we picked up in framebuffer lookup */
-	drm_framebuffer_unreference(fb);
-
-	/*
-	 * we now own the reference that was stored in the fbs list
-	 *
-	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
-	 * so run this in a separate stack as there's no way to correctly
-	 * handle this after the fb is already removed from the lookup table.
-	 */
-	if (drm_framebuffer_read_refcount(fb) > 1) {
-		struct drm_mode_rmfb_work arg;
-
-		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-		INIT_LIST_HEAD(&arg.fbs);
-		list_add_tail(&fb->filp_head, &arg.fbs);
-
-		schedule_work(&arg.work);
-		flush_work(&arg.work);
-		destroy_work_on_stack(&arg.work);
-	} else
-		drm_framebuffer_unreference(fb);
-
-	return 0;
-
-fail_unref:
-	drm_framebuffer_unreference(fb);
-	return -ENOENT;
-}
-
-/**
- * drm_mode_getfb - get FB info
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Lookup the FB given its ID and return info about it.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd *r = data;
-	struct drm_framebuffer *fb;
-	int ret;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, r->fb_id);
-	if (!fb)
-		return -ENOENT;
-
-	r->height = fb->height;
-	r->width = fb->width;
-	r->depth = fb->depth;
-	r->bpp = fb->bits_per_pixel;
-	r->pitch = fb->pitches[0];
-	if (fb->funcs->create_handle) {
-		if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
-		    drm_is_control_client(file_priv)) {
-			ret = fb->funcs->create_handle(fb, file_priv,
-						       &r->handle);
-		} else {
-			/* GET_FB() is an unprivileged ioctl so we must not
-			 * return a buffer-handle to non-master processes! For
-			 * backwards-compatibility reasons, we cannot make
-			 * GET_FB() privileged, so just return an invalid handle
-			 * for non-masters. */
-			r->handle = 0;
-			ret = 0;
-		}
-	} else {
-		ret = -ENODEV;
-	}
-
-	drm_framebuffer_unreference(fb);
-
-	return ret;
-}
-
-/**
- * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Lookup the FB and flush out the damaged area supplied by userspace as a clip
- * rectangle list. Generic userspace which does frontbuffer rendering must call
- * this ioctl to flush out the changes on manual-update display outputs, e.g.
- * usb display-link, mipi manual update panels or edp panel self refresh modes.
- *
- * Modesetting drivers which always update the frontbuffer do not need to
- * implement the corresponding ->dirty framebuffer callback.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv)
-{
-	struct drm_clip_rect __user *clips_ptr;
-	struct drm_clip_rect *clips = NULL;
-	struct drm_mode_fb_dirty_cmd *r = data;
-	struct drm_framebuffer *fb;
-	unsigned flags;
-	int num_clips;
-	int ret;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, r->fb_id);
-	if (!fb)
-		return -ENOENT;
-
-	num_clips = r->num_clips;
-	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
-
-	if (!num_clips != !clips_ptr) {
-		ret = -EINVAL;
-		goto out_err1;
-	}
-
-	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
-
-	/* If userspace annotates copy, clips must come in pairs */
-	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
-		ret = -EINVAL;
-		goto out_err1;
-	}
-
-	if (num_clips && clips_ptr) {
-		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
-			ret = -EINVAL;
-			goto out_err1;
-		}
-		clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
-		if (!clips) {
-			ret = -ENOMEM;
-			goto out_err1;
-		}
-
-		ret = copy_from_user(clips, clips_ptr,
-				     num_clips * sizeof(*clips));
-		if (ret) {
-			ret = -EFAULT;
-			goto out_err2;
-		}
-	}
-
-	if (fb->funcs->dirty) {
-		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
-				       clips, num_clips);
-	} else {
-		ret = -ENOSYS;
-	}
-
-out_err2:
-	kfree(clips);
-out_err1:
-	drm_framebuffer_unreference(fb);
-
-	return ret;
-}
-
-/**
- * drm_fb_release - remove and free the FBs on this file
- * @priv: drm file for the ioctl
- *
- * Destroy all the FBs associated with @filp.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-void drm_fb_release(struct drm_file *priv)
-{
-	struct drm_framebuffer *fb, *tfb;
-	struct drm_mode_rmfb_work arg;
-
-	INIT_LIST_HEAD(&arg.fbs);
-
-	/*
-	 * When the file gets released that means no one else can access the fb
-	 * list any more, so no need to grab fpriv->fbs_lock. And we need to
-	 * avoid upsetting lockdep since the universal cursor code adds a
-	 * framebuffer while holding mutex locks.
-	 *
-	 * Note that a real deadlock between fpriv->fbs_lock and the modeset
-	 * locks is impossible here since no one else but this function can get
-	 * at it any more.
-	 */
-	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
-		if (drm_framebuffer_read_refcount(fb) > 1) {
-			list_move_tail(&fb->filp_head, &arg.fbs);
-		} else {
-			list_del_init(&fb->filp_head);
-
-			/* This drops the fpriv->fbs reference. */
-			drm_framebuffer_unreference(fb);
-		}
-	}
-
-	if (!list_empty(&arg.fbs)) {
-		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-
-		schedule_work(&arg.work);
-		flush_work(&arg.work);
-		destroy_work_on_stack(&arg.work);
-	}
-}
-
 static bool drm_property_type_valid(struct drm_property *property)
 {
 	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
@@ -4492,7 +3717,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 	struct drm_mode_object *obj;
 	struct drm_property_blob *blob = NULL;
 
-	obj = _object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
 	if (obj)
 		blob = obj_to_blob(obj);
 	return blob;
@@ -4888,7 +4113,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
 		if (value == 0)
 			return true;
 
-		*ref = _object_find(property->dev, value, property->values[0]);
+		*ref = __drm_mode_object_find(property->dev, value,
+					      property->values[0]);
 		return *ref != NULL;
 	}
 
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 3ea72e1780b1..5f1e9ff71ae4 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -35,8 +35,17 @@
 /* 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,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref));
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj);
 int drm_mode_object_get(struct drm_device *dev,
 			struct drm_mode_object *obj, uint32_t obj_type);
+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);
 bool drm_property_change_valid_get(struct drm_property *property,
@@ -64,18 +73,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 
-/* framebuffer IOCTLs */
-extern int drm_mode_addfb(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv);
-extern int drm_mode_addfb2(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv);
-int drm_mode_rmfb(struct drm_device *dev,
-			 void *data, struct drm_file *file_priv);
-int drm_mode_getfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv);
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv);
-
 /* IOCTLs */
 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file_priv);
@@ -120,6 +117,25 @@ 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_framebuffer.c */
+struct drm_framebuffer *
+drm_internal_framebuffer_create(struct drm_device *dev,
+				const struct drm_mode_fb_cmd2 *r,
+				struct drm_file *file_priv);
+void drm_framebuffer_free(struct kref *kref);
+
+/* IOCTL */
+int drm_mode_addfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv);
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv);
+int drm_mode_rmfb(struct drm_device *dev,
+		  void *data, struct drm_file *file_priv);
+int drm_mode_getfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv);
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv);
+
 /* drm_atomic.c */
 int drm_atomic_get_property(struct drm_mode_object *obj,
 			    struct drm_property *property, uint64_t *val);
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
new file mode 100644
index 000000000000..19478a25ac20
--- /dev/null
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -0,0 +1,799 @@
+/*
+ * 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 <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_framebuffer.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * drm_mode_addfb - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request. This is the
+ * original addfb ioctl which only supported RGB formats.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_addfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd *or = data;
+	struct drm_mode_fb_cmd2 r = {};
+	int ret;
+
+	/* convert to new format and call new ioctl */
+	r.fb_id = or->fb_id;
+	r.width = or->width;
+	r.height = or->height;
+	r.pitches[0] = or->pitch;
+	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
+	r.handles[0] = or->handle;
+
+	ret = drm_mode_addfb2(dev, &r, file_priv);
+	if (ret)
+		return ret;
+
+	or->fb_id = r.fb_id;
+
+	return 0;
+}
+
+static int format_check(const struct drm_mode_fb_cmd2 *r)
+{
+	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_BGR233:
+	case DRM_FORMAT_XRGB4444:
+	case DRM_FORMAT_XBGR4444:
+	case DRM_FORMAT_RGBX4444:
+	case DRM_FORMAT_BGRX4444:
+	case DRM_FORMAT_ARGB4444:
+	case DRM_FORMAT_ABGR4444:
+	case DRM_FORMAT_RGBA4444:
+	case DRM_FORMAT_BGRA4444:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_AYUV:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return 0;
+	default:
+		DRM_DEBUG_KMS("invalid pixel format %s\n",
+			      drm_get_format_name(r->pixel_format));
+		return -EINVAL;
+	}
+}
+
+static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
+{
+	int ret, hsub, vsub, num_planes, i;
+
+	ret = format_check(r);
+	if (ret) {
+		DRM_DEBUG_KMS("bad framebuffer format %s\n",
+			      drm_get_format_name(r->pixel_format));
+		return ret;
+	}
+
+	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
+	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
+	num_planes = drm_format_num_planes(r->pixel_format);
+
+	if (r->width == 0 || r->width % hsub) {
+		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
+		return -EINVAL;
+	}
+
+	if (r->height == 0 || r->height % vsub) {
+		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_planes; i++) {
+		unsigned int width = r->width / (i != 0 ? hsub : 1);
+		unsigned int height = r->height / (i != 0 ? vsub : 1);
+		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
+
+		if (!r->handles[i]) {
+			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if ((uint64_t) width * cpp > UINT_MAX)
+			return -ERANGE;
+
+		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
+			return -ERANGE;
+
+		if (r->pitches[i] < width * cpp) {
+			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
+			return -EINVAL;
+		}
+
+		if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
+			DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
+				      r->modifier[i], i);
+			return -EINVAL;
+		}
+
+		/* modifier specific checks: */
+		switch (r->modifier[i]) {
+		case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
+			/* NOTE: the pitch restriction may be lifted later if it turns
+			 * out that no hw has this restriction:
+			 */
+			if (r->pixel_format != DRM_FORMAT_NV12 ||
+					width % 128 || height % 32 ||
+					r->pitches[i] % 128) {
+				DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
+				return -EINVAL;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	for (i = num_planes; i < 4; i++) {
+		if (r->modifier[i]) {
+			DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
+		if (!(r->flags & DRM_MODE_FB_MODIFIERS))
+			continue;
+
+		if (r->handles[i]) {
+			DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if (r->pitches[i]) {
+			DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if (r->offsets[i]) {
+			DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct drm_framebuffer *
+drm_internal_framebuffer_create(struct drm_device *dev,
+				const struct drm_mode_fb_cmd2 *r,
+				struct drm_file *file_priv)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
+		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if ((config->min_width > r->width) || (r->width > config->max_width)) {
+		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
+			  r->width, config->min_width, config->max_width);
+		return ERR_PTR(-EINVAL);
+	}
+	if ((config->min_height > r->height) || (r->height > config->max_height)) {
+		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
+			  r->height, config->min_height, config->max_height);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (r->flags & DRM_MODE_FB_MODIFIERS &&
+	    !dev->mode_config.allow_fb_modifiers) {
+		DRM_DEBUG_KMS("driver does not support fb modifiers\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = framebuffer_check(r);
+	if (ret)
+		return ERR_PTR(ret);
+
+	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
+	if (IS_ERR(fb)) {
+		DRM_DEBUG_KMS("could not create framebuffer\n");
+		return fb;
+	}
+
+	return fb;
+}
+
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request with format. This is
+ * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
+ * and uses fourcc codes as pixel format specifiers.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd2 *r = data;
+	struct drm_framebuffer *fb;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_internal_framebuffer_create(dev, r, file_priv);
+	if (IS_ERR(fb))
+		return PTR_ERR(fb);
+
+	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
+	r->fb_id = fb->base.id;
+
+	/* Transfer ownership to the filp for reaping on close */
+	mutex_lock(&file_priv->fbs_lock);
+	list_add(&fb->filp_head, &file_priv->fbs);
+	mutex_unlock(&file_priv->fbs_lock);
+
+	return 0;
+}
+
+struct drm_mode_rmfb_work {
+	struct work_struct work;
+	struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+	while (!list_empty(&arg->fbs)) {
+		struct drm_framebuffer *fb =
+			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+		list_del_init(&fb->filp_head);
+		drm_framebuffer_remove(fb);
+	}
+}
+
+/**
+ * drm_mode_rmfb - remove an FB from the configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Remove the FB specified by the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_rmfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_framebuffer *fb = NULL;
+	struct drm_framebuffer *fbl = NULL;
+	uint32_t *id = data;
+	int found = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, *id);
+	if (!fb)
+		return -ENOENT;
+
+	mutex_lock(&file_priv->fbs_lock);
+	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
+		if (fb == fbl)
+			found = 1;
+	if (!found) {
+		mutex_unlock(&file_priv->fbs_lock);
+		goto fail_unref;
+	}
+
+	list_del_init(&fb->filp_head);
+	mutex_unlock(&file_priv->fbs_lock);
+
+	/* drop the reference we picked up in framebuffer lookup */
+	drm_framebuffer_unreference(fb);
+
+	/*
+	 * we now own the reference that was stored in the fbs list
+	 *
+	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
+	 * so run this in a separate stack as there's no way to correctly
+	 * handle this after the fb is already removed from the lookup table.
+	 */
+	if (drm_framebuffer_read_refcount(fb) > 1) {
+		struct drm_mode_rmfb_work arg;
+
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+		INIT_LIST_HEAD(&arg.fbs);
+		list_add_tail(&fb->filp_head, &arg.fbs);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	} else
+		drm_framebuffer_unreference(fb);
+
+	return 0;
+
+fail_unref:
+	drm_framebuffer_unreference(fb);
+	return -ENOENT;
+}
+
+/**
+ * drm_mode_getfb - get FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd *r = data;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, r->fb_id);
+	if (!fb)
+		return -ENOENT;
+
+	r->height = fb->height;
+	r->width = fb->width;
+	r->depth = fb->depth;
+	r->bpp = fb->bits_per_pixel;
+	r->pitch = fb->pitches[0];
+	if (fb->funcs->create_handle) {
+		if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
+		    drm_is_control_client(file_priv)) {
+			ret = fb->funcs->create_handle(fb, file_priv,
+						       &r->handle);
+		} else {
+			/* GET_FB() is an unprivileged ioctl so we must not
+			 * return a buffer-handle to non-master processes! For
+			 * backwards-compatibility reasons, we cannot make
+			 * GET_FB() privileged, so just return an invalid handle
+			 * for non-masters. */
+			r->handle = 0;
+			ret = 0;
+		}
+	} else {
+		ret = -ENODEV;
+	}
+
+	drm_framebuffer_unreference(fb);
+
+	return ret;
+}
+
+/**
+ * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB and flush out the damaged area supplied by userspace as a clip
+ * rectangle list. Generic userspace which does frontbuffer rendering must call
+ * this ioctl to flush out the changes on manual-update display outputs, e.g.
+ * usb display-link, mipi manual update panels or edp panel self refresh modes.
+ *
+ * Modesetting drivers which always update the frontbuffer do not need to
+ * implement the corresponding ->dirty framebuffer callback.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	struct drm_clip_rect __user *clips_ptr;
+	struct drm_clip_rect *clips = NULL;
+	struct drm_mode_fb_dirty_cmd *r = data;
+	struct drm_framebuffer *fb;
+	unsigned flags;
+	int num_clips;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, r->fb_id);
+	if (!fb)
+		return -ENOENT;
+
+	num_clips = r->num_clips;
+	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
+
+	if (!num_clips != !clips_ptr) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
+
+	/* If userspace annotates copy, clips must come in pairs */
+	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	if (num_clips && clips_ptr) {
+		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+			ret = -EINVAL;
+			goto out_err1;
+		}
+		clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+		if (!clips) {
+			ret = -ENOMEM;
+			goto out_err1;
+		}
+
+		ret = copy_from_user(clips, clips_ptr,
+				     num_clips * sizeof(*clips));
+		if (ret) {
+			ret = -EFAULT;
+			goto out_err2;
+		}
+	}
+
+	if (fb->funcs->dirty) {
+		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
+				       clips, num_clips);
+	} else {
+		ret = -ENOSYS;
+	}
+
+out_err2:
+	kfree(clips);
+out_err1:
+	drm_framebuffer_unreference(fb);
+
+	return ret;
+}
+
+/**
+ * drm_fb_release - remove and free the FBs on this file
+ * @priv: drm file for the ioctl
+ *
+ * Destroy all the FBs associated with @filp.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+void drm_fb_release(struct drm_file *priv)
+{
+	struct drm_framebuffer *fb, *tfb;
+	struct drm_mode_rmfb_work arg;
+
+	INIT_LIST_HEAD(&arg.fbs);
+
+	/*
+	 * When the file gets released that means no one else can access the fb
+	 * list any more, so no need to grab fpriv->fbs_lock. And we need to
+	 * avoid upsetting lockdep since the universal cursor code adds a
+	 * framebuffer while holding mutex locks.
+	 *
+	 * Note that a real deadlock between fpriv->fbs_lock and the modeset
+	 * locks is impossible here since no one else but this function can get
+	 * at it any more.
+	 */
+	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+		if (drm_framebuffer_read_refcount(fb) > 1) {
+			list_move_tail(&fb->filp_head, &arg.fbs);
+		} else {
+			list_del_init(&fb->filp_head);
+
+			/* This drops the fpriv->fbs reference. */
+			drm_framebuffer_unreference(fb);
+		}
+	}
+
+	if (!list_empty(&arg.fbs)) {
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	}
+}
+
+void drm_framebuffer_free(struct kref *kref)
+{
+	struct drm_framebuffer *fb =
+			container_of(kref, struct drm_framebuffer, base.refcount);
+	struct drm_device *dev = fb->dev;
+
+	/*
+	 * The lookup idr holds a weak reference, which has not necessarily been
+	 * removed at this point. Check for that.
+	 */
+	drm_mode_object_unregister(dev, &fb->base);
+
+	fb->funcs->destroy(fb);
+}
+
+/**
+ * drm_framebuffer_init - initialize a framebuffer
+ * @dev: DRM device
+ * @fb: framebuffer to be initialized
+ * @funcs: ... with these functions
+ *
+ * Allocates an ID for the framebuffer's parent mode object, sets its mode
+ * functions & device file and adds it to the master fd list.
+ *
+ * IMPORTANT:
+ * This functions publishes the fb and makes it available for concurrent access
+ * by other users. Which means by this point the fb _must_ be fully set up -
+ * since all the fb attributes are invariant over its lifetime, no further
+ * locking but only correct reference counting is required.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+			 const struct drm_framebuffer_funcs *funcs)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&fb->filp_head);
+	fb->dev = dev;
+	fb->funcs = funcs;
+
+	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
+				      false, drm_framebuffer_free);
+	if (ret)
+		goto out;
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	dev->mode_config.num_fb++;
+	list_add(&fb->head, &dev->mode_config.fb_list);
+	mutex_unlock(&dev->mode_config.fb_lock);
+
+	drm_mode_object_register(dev, &fb->base);
+out:
+	return ret;
+}
+EXPORT_SYMBOL(drm_framebuffer_init);
+
+/**
+ * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
+ * @dev: drm device
+ * @id: id of the fb object
+ *
+ * If successful, this grabs an additional reference to the framebuffer -
+ * callers need to make sure to eventually unreference the returned framebuffer
+ * again, using @drm_framebuffer_unreference.
+ */
+struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
+
+	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
+	return fb;
+}
+EXPORT_SYMBOL(drm_framebuffer_lookup);
+
+/**
+ * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
+ * @fb: fb to unregister
+ *
+ * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
+ * those used for fbdev. Note that the caller must hold a reference of it's own,
+ * i.e. the object may not be destroyed through this call (since it'll lead to a
+ * locking inversion).
+ */
+void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev;
+
+	if (!fb)
+		return;
+
+	dev = fb->dev;
+
+	/* Mark fb as reaped and drop idr ref. */
+	drm_mode_object_unregister(dev, &fb->base);
+}
+EXPORT_SYMBOL(drm_framebuffer_unregister_private);
+
+/**
+ * drm_framebuffer_cleanup - remove a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * Cleanup framebuffer. This function is intended to be used from the drivers
+ * ->destroy callback. It can also be used to clean up driver private
+ * framebuffers embedded into a larger structure.
+ *
+ * Note that this function does not remove the fb from active usuage - if it is
+ * still used anywhere, hilarity can ensue since userspace could call getfb on
+ * the id and get back -EINVAL. Obviously no concern at driver unload time.
+ *
+ * Also, the framebuffer will not be removed from the lookup idr - for
+ * user-created framebuffers this will happen in in the rmfb ioctl. For
+ * driver-private objects (e.g. for fbdev) drivers need to explicitly call
+ * drm_framebuffer_unregister_private.
+ */
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = fb->dev;
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	list_del(&fb->head);
+	dev->mode_config.num_fb--;
+	mutex_unlock(&dev->mode_config.fb_lock);
+}
+EXPORT_SYMBOL(drm_framebuffer_cleanup);
+
+/**
+ * drm_framebuffer_remove - remove and unreference a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * Scans all the CRTCs and planes in @dev's mode_config.  If they're
+ * using @fb, removes it, setting it to NULL. Then drops the reference to the
+ * passed-in framebuffer. Might take the modeset locks.
+ *
+ * Note that this function optimizes the cleanup away if the caller holds the
+ * last reference to the framebuffer. It is also guaranteed to not take the
+ * modeset locks in this case.
+ */
+void drm_framebuffer_remove(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+
+	if (!fb)
+		return;
+
+	dev = fb->dev;
+
+	WARN_ON(!list_empty(&fb->filp_head));
+
+	/*
+	 * drm ABI mandates that we remove any deleted framebuffers from active
+	 * useage. But since most sane clients only remove framebuffers they no
+	 * longer need, try to optimize this away.
+	 *
+	 * Since we're holding a reference ourselves, observing a refcount of 1
+	 * means that we're the last holder and can skip it. Also, the refcount
+	 * can never increase from 1 again, so we don't need any barriers or
+	 * locks.
+	 *
+	 * Note that userspace could try to race with use and instate a new
+	 * usage _after_ we've cleared all current ones. End result will be an
+	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
+	 * in this manner.
+	 */
+	if (drm_framebuffer_read_refcount(fb) > 1) {
+		if (dev->mode_config.funcs->atomic_commit) {
+			drm_atomic_remove_fb(fb);
+			goto out;
+		}
+
+		drm_modeset_lock_all(dev);
+		/* remove from any CRTC */
+		drm_for_each_crtc(crtc, dev) {
+			if (crtc->primary->fb == fb) {
+				/* should turn off the crtc */
+				if (drm_crtc_force_disable(crtc))
+					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
+			}
+		}
+
+		drm_for_each_plane(plane, dev) {
+			if (plane->fb == fb)
+				drm_plane_force_disable(plane);
+		}
+		drm_modeset_unlock_all(dev);
+	}
+
+out:
+	drm_framebuffer_unreference(fb);
+}
+EXPORT_SYMBOL(drm_framebuffer_remove);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5a7809f029ba..0119161cad57 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -36,10 +36,12 @@
 #include <uapi/drm/drm_fourcc.h>
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_modeset.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modes.h>
 
 struct drm_device;
 struct drm_mode_set;
-struct drm_framebuffer;
 struct drm_object_properties;
 struct drm_file;
 struct drm_clip_rect;
@@ -47,14 +49,6 @@ struct device_node;
 struct fence;
 struct edid;
 
-struct drm_mode_object {
-	uint32_t id;
-	uint32_t type;
-	struct drm_object_properties *properties;
-	struct kref refcount;
-	void (*free_cb)(struct kref *kref);
-};
-
 #define DRM_OBJECT_MAX_PROPERTY 24
 struct drm_object_properties {
 	int count, atomic_count;
@@ -94,15 +88,6 @@ static inline uint64_t I642U64(int64_t val)
 #define DRM_REFLECT_Y	BIT(5)
 #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
 
-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 */
-};
-
-#include <drm/drm_modes.h>
-
 enum drm_connector_status {
 	connector_status_connected = 1,
 	connector_status_disconnected = 2,
@@ -166,101 +151,6 @@ struct drm_tile_group {
 	u8 group_data[8];
 };
 
-/**
- * struct drm_framebuffer_funcs - framebuffer hooks
- */
-struct drm_framebuffer_funcs {
-	/**
-	 * @destroy:
-	 *
-	 * Clean up framebuffer resources, specifically also unreference the
-	 * backing storage. The core guarantees to call this function for every
-	 * framebuffer successfully created by ->fb_create() in
-	 * &drm_mode_config_funcs. Drivers must also call
-	 * drm_framebuffer_cleanup() to release DRM core resources for this
-	 * framebuffer.
-	 */
-	void (*destroy)(struct drm_framebuffer *framebuffer);
-
-	/**
-	 * @create_handle:
-	 *
-	 * Create a buffer handle in the driver-specific buffer manager (either
-	 * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
-	 * the core to implement the GETFB IOCTL, which returns (for
-	 * sufficiently priviledged user) also a native buffer handle. This can
-	 * be used for seamless transitions between modesetting clients by
-	 * copying the current screen contents to a private buffer and blending
-	 * between that and the new contents.
-	 *
-	 * GEM based drivers should call drm_gem_handle_create() to create the
-	 * handle.
-	 *
-	 * RETURNS:
-	 *
-	 * 0 on success or a negative error code on failure.
-	 */
-	int (*create_handle)(struct drm_framebuffer *fb,
-			     struct drm_file *file_priv,
-			     unsigned int *handle);
-	/**
-	 * @dirty:
-	 *
-	 * Optional callback for the dirty fb IOCTL.
-	 *
-	 * Userspace can notify the driver via this callback that an area of the
-	 * framebuffer has changed and should be flushed to the display
-	 * hardware. This can also be used internally, e.g. by the fbdev
-	 * emulation, though that's not the case currently.
-	 *
-	 * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
-	 * for more information as all the semantics and arguments have a one to
-	 * one mapping on this function.
-	 *
-	 * RETURNS:
-	 *
-	 * 0 on success or a negative error code on failure.
-	 */
-	int (*dirty)(struct drm_framebuffer *framebuffer,
-		     struct drm_file *file_priv, unsigned flags,
-		     unsigned color, struct drm_clip_rect *clips,
-		     unsigned num_clips);
-};
-
-struct drm_framebuffer {
-	struct drm_device *dev;
-	/*
-	 * Note that the fb is refcounted for the benefit of driver internals,
-	 * for example some hw, disabling a CRTC/plane is asynchronous, and
-	 * scanout does not actually complete until the next vblank.  So some
-	 * cleanup (like releasing the reference(s) on the backing GEM bo(s))
-	 * should be deferred.  In cases like this, the driver would like to
-	 * hold a ref to the fb even though it has already been removed from
-	 * userspace perspective.
-	 * The refcount is stored inside the mode object.
-	 */
-	/*
-	 * Place on the dev->mode_config.fb_list, access protected by
-	 * dev->mode_config.fb_lock.
-	 */
-	struct list_head head;
-	struct drm_mode_object base;
-	const struct drm_framebuffer_funcs *funcs;
-	unsigned int pitches[4];
-	unsigned int offsets[4];
-	uint64_t modifier[4];
-	unsigned int width;
-	unsigned int height;
-	/* depth can be 15 or 16 */
-	unsigned int depth;
-	int bits_per_pixel;
-	int flags;
-	uint32_t pixel_format; /* fourcc format */
-	int hot_x;
-	int hot_y;
-	struct list_head filp_head;
-};
-
 struct drm_property_blob {
 	struct drm_mode_object base;
 	struct drm_device *dev;
@@ -2888,14 +2778,6 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,
 extern int drm_object_property_get_value(struct drm_mode_object *obj,
 					 struct drm_property *property,
 					 uint64_t *value);
-extern int drm_framebuffer_init(struct drm_device *dev,
-				struct drm_framebuffer *fb,
-				const struct drm_framebuffer_funcs *funcs);
-extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
-						      uint32_t id);
-extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
-extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
-extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
 
 extern void drm_object_attach_property(struct drm_mode_object *obj,
 				       struct drm_property *property,
@@ -2976,11 +2858,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
 					     unsigned int zpos);
 
 /* Helpers */
-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);
-
 static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
 		uint32_t id)
 {
@@ -3049,39 +2926,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
 }
 
 /**
- * drm_framebuffer_reference - incr the fb refcnt
- * @fb: framebuffer
- *
- * This functions increments the fb's refcount.
- */
-static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
-{
-	drm_mode_object_reference(&fb->base);
-}
-
-/**
- * drm_framebuffer_unreference - unref a framebuffer
- * @fb: framebuffer to unref
- *
- * This functions decrements the fb's refcount and frees it if it drops to zero.
- */
-static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
-{
-	drm_mode_object_unreference(&fb->base);
-}
-
-/**
- * drm_framebuffer_read_refcount - read the framebuffer reference count.
- * @fb: framebuffer
- *
- * This functions returns the framebuffer's reference count.
- */
-static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
-{
-	return atomic_read(&fb->base.refcount.refcount);
-}
-
-/**
  * drm_connector_reference - incr the connector refcnt
  * @connector: connector
  *
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
new file mode 100644
index 000000000000..46abdace8fa5
--- /dev/null
+++ b/include/drm/drm_framebuffer.h
@@ -0,0 +1,170 @@
+/*
+ * 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_FRAMEBUFFER_H__
+#define __DRM_FRAMEBUFFER_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_modeset.h>
+
+struct drm_framebuffer;
+struct drm_file;
+struct drm_device;
+
+/**
+ * struct drm_framebuffer_funcs - framebuffer hooks
+ */
+struct drm_framebuffer_funcs {
+	/**
+	 * @destroy:
+	 *
+	 * Clean up framebuffer resources, specifically also unreference the
+	 * backing storage. The core guarantees to call this function for every
+	 * framebuffer successfully created by ->fb_create() in
+	 * &drm_mode_config_funcs. Drivers must also call
+	 * drm_framebuffer_cleanup() to release DRM core resources for this
+	 * framebuffer.
+	 */
+	void (*destroy)(struct drm_framebuffer *framebuffer);
+
+	/**
+	 * @create_handle:
+	 *
+	 * Create a buffer handle in the driver-specific buffer manager (either
+	 * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
+	 * the core to implement the GETFB IOCTL, which returns (for
+	 * sufficiently priviledged user) also a native buffer handle. This can
+	 * be used for seamless transitions between modesetting clients by
+	 * copying the current screen contents to a private buffer and blending
+	 * between that and the new contents.
+	 *
+	 * GEM based drivers should call drm_gem_handle_create() to create the
+	 * handle.
+	 *
+	 * RETURNS:
+	 *
+	 * 0 on success or a negative error code on failure.
+	 */
+	int (*create_handle)(struct drm_framebuffer *fb,
+			     struct drm_file *file_priv,
+			     unsigned int *handle);
+	/**
+	 * @dirty:
+	 *
+	 * Optional callback for the dirty fb IOCTL.
+	 *
+	 * Userspace can notify the driver via this callback that an area of the
+	 * framebuffer has changed and should be flushed to the display
+	 * hardware. This can also be used internally, e.g. by the fbdev
+	 * emulation, though that's not the case currently.
+	 *
+	 * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
+	 * for more information as all the semantics and arguments have a one to
+	 * one mapping on this function.
+	 *
+	 * RETURNS:
+	 *
+	 * 0 on success or a negative error code on failure.
+	 */
+	int (*dirty)(struct drm_framebuffer *framebuffer,
+		     struct drm_file *file_priv, unsigned flags,
+		     unsigned color, struct drm_clip_rect *clips,
+		     unsigned num_clips);
+};
+
+struct drm_framebuffer {
+	struct drm_device *dev;
+	/*
+	 * Note that the fb is refcounted for the benefit of driver internals,
+	 * for example some hw, disabling a CRTC/plane is asynchronous, and
+	 * scanout does not actually complete until the next vblank.  So some
+	 * cleanup (like releasing the reference(s) on the backing GEM bo(s))
+	 * should be deferred.  In cases like this, the driver would like to
+	 * hold a ref to the fb even though it has already been removed from
+	 * userspace perspective.
+	 * The refcount is stored inside the mode object.
+	 */
+	/*
+	 * Place on the dev->mode_config.fb_list, access protected by
+	 * dev->mode_config.fb_lock.
+	 */
+	struct list_head head;
+	struct drm_mode_object base;
+	const struct drm_framebuffer_funcs *funcs;
+	unsigned int pitches[4];
+	unsigned int offsets[4];
+	uint64_t modifier[4];
+	unsigned int width;
+	unsigned int height;
+	/* depth can be 15 or 16 */
+	unsigned int depth;
+	int bits_per_pixel;
+	int flags;
+	uint32_t pixel_format; /* fourcc format */
+	int hot_x;
+	int hot_y;
+	struct list_head filp_head;
+};
+
+int drm_framebuffer_init(struct drm_device *dev,
+			 struct drm_framebuffer *fb,
+			 const struct drm_framebuffer_funcs *funcs);
+struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id);
+void drm_framebuffer_remove(struct drm_framebuffer *fb);
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
+void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
+
+/**
+ * drm_framebuffer_reference - incr the fb refcnt
+ * @fb: framebuffer
+ *
+ * This functions increments the fb's refcount.
+ */
+static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
+{
+	drm_mode_object_reference(&fb->base);
+}
+
+/**
+ * drm_framebuffer_unreference - unref a framebuffer
+ * @fb: framebuffer to unref
+ *
+ * This functions decrements the fb's refcount and frees it if it drops to zero.
+ */
+static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
+{
+	drm_mode_object_unreference(&fb->base);
+}
+
+/**
+ * drm_framebuffer_read_refcount - read the framebuffer reference count.
+ * @fb: framebuffer
+ *
+ * This functions returns the framebuffer's reference count.
+ */
+static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
+{
+	return atomic_read(&fb->base.refcount.refcount);
+}
+#endif
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index ff481770d76b..f0af1edcbefe 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -27,6 +27,8 @@
 #ifndef __DRM_MODES_H__
 #define __DRM_MODES_H__
 
+#include <drm/drm_modeset.h>
+
 /*
  * Note on terminology:  here, for brevity and convenience, we refer to connector
  * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
diff --git a/include/drm/drm_modeset.h b/include/drm/drm_modeset.h
new file mode 100644
index 000000000000..0c2b0f3c5f34
--- /dev/null
+++ b/include/drm/drm_modeset.h
@@ -0,0 +1,50 @@
+/*
+ * 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_MODESET_H__
+#define __DRM_MODESET_H__
+
+#include <linux/kref.h>
+struct drm_object_properties;
+
+struct drm_mode_object {
+	uint32_t id;
+	uint32_t type;
+	struct drm_object_properties *properties;
+	struct kref refcount;
+	void (*free_cb)(struct kref *kref);
+};
+
+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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 12/21] drm/doc: Update drm_framebuffer docs
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (9 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 11/21] drm: Extract drm_framebuffer.[hc] Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-16 16:11   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 13/21] drm: Export drm_property_replace_global_blob Daniel Vetter
                   ` (9 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Move the intro section into a DOC comment, and update it slightly.
- kernel-doc for struct drm_framebuffer!

v2:
- Copypaste fail (Sean).
- Explain the linear @offsets clearer (Ville).

Cc: Sean Paul <seanpaul@chromium.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst     |  26 +---------
 drivers/gpu/drm/drm_framebuffer.c |  35 +++++++++++++
 include/drm/drm_framebuffer.h     | 106 +++++++++++++++++++++++++++++++++-----
 3 files changed, 130 insertions(+), 37 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 8264a88a8695..d244e03658cc 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -39,30 +39,8 @@ Atomic Mode Setting Function Reference
 Frame Buffer Abstraction
 ========================
 
-Frame buffers are abstract memory objects that provide a source of
-pixels to scanout to a CRTC. Applications explicitly request the
-creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls
-and receive an opaque handle that can be passed to the KMS CRTC control,
-plane configuration and page flip functions.
-
-Frame buffers rely on the underneath memory manager for low-level memory
-operations. When creating a frame buffer applications pass a memory
-handle (or a list of memory handles for multi-planar formats) through
-the ``drm_mode_fb_cmd2`` argument. For drivers using GEM as their
-userspace buffer management interface this would be a GEM handle.
-Drivers are however free to use their own backing storage object
-handles, e.g. vmwgfx directly exposes special TTM handles to userspace
-and so expects TTM handles in the create ioctl and not GEM handles.
-
-The lifetime of a drm framebuffer is controlled with a reference count,
-drivers can grab additional references with
-:c:func:`drm_framebuffer_reference()`and drop them again with
-:c:func:`drm_framebuffer_unreference()`. For driver-private
-framebuffers for which the last reference is never dropped (e.g. for the
-fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
-<drm_framebuffer>` is embedded into the fbdev helper struct)
-drivers can manually clean up a framebuffer at module unload time with
-:c:func:`drm_framebuffer_unregister_private()`.
+.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
+   :doc: overview
 
 Frame Buffer Functions Reference
 --------------------------------
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index 19478a25ac20..34e3c4acbc8a 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -28,6 +28,41 @@
 #include "drm_crtc_internal.h"
 
 /**
+ * DOC: overview
+ *
+ * Frame buffers are abstract memory objects that provide a source of pixels to
+ * scanout to a CRTC. Applications explicitly request the creation of frame
+ * buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and receive an opaque
+ * handle that can be passed to the KMS CRTC control, plane configuration and
+ * page flip functions.
+ *
+ * Frame buffers rely on the underlying memory manager for allocating backing
+ * storage. When creating a frame buffer applications pass a memory handle
+ * (or a list of memory handles for multi-planar formats) through the
+ * struct &drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace
+ * buffer management interface this would be a GEM handle.  Drivers are however
+ * free to use their own backing storage object handles, e.g. vmwgfx directly
+ * exposes special TTM handles to userspace and so expects TTM handles in the
+ * create ioctl and not GEM handles.
+ *
+ * Framebuffers are tracked with struct &drm_framebuffer. They are published
+ * using drm_framebuffer_init() - after calling that function userspace can use
+ * and access the framebuffer object. The helper function
+ * drm_helper_mode_fill_fb_struct() can be used to pre-fill the required
+ * metadata fields.
+ *
+ * The lifetime of a drm framebuffer is controlled with a reference count,
+ * drivers can grab additional references with drm_framebuffer_reference() and
+ * drop them again with drm_framebuffer_unreference(). For driver-private
+ * framebuffers for which the last reference is never dropped (e.g. for the
+ * fbdev framebuffer when the struct struct &drm_framebuffer is embedded into
+ * the fbdev helper struct) drivers can manually clean up a framebuffer at
+ * module unload time with drm_framebuffer_unregister_private(). But doing this
+ * is not recommended, and it's better to have a normal free-standing struct
+ * &drm_framebuffer.
+ */
+
+/**
  * drm_mode_addfb - add an FB to the graphics configuration
  * @dev: drm device for the ioctl
  * @data: data pointer for the ioctl
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 46abdace8fa5..50deb40d3bfd 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -92,37 +92,117 @@ struct drm_framebuffer_funcs {
 		     unsigned num_clips);
 };
 
+/**
+ * struct drm_framebuffer - frame buffer object
+ *
+ * Note that the fb is refcounted for the benefit of driver internals,
+ * for example some hw, disabling a CRTC/plane is asynchronous, and
+ * scanout does not actually complete until the next vblank.  So some
+ * cleanup (like releasing the reference(s) on the backing GEM bo(s))
+ * should be deferred.  In cases like this, the driver would like to
+ * hold a ref to the fb even though it has already been removed from
+ * userspace perspective. See drm_framebuffer_reference() and
+ * drm_framebuffer_unreference().
+ *
+ * The refcount is stored inside the mode object @base.
+ */
 struct drm_framebuffer {
+	/**
+	 * @dev: DRM device this framebuffer belongs to
+	 */
 	struct drm_device *dev;
-	/*
-	 * Note that the fb is refcounted for the benefit of driver internals,
-	 * for example some hw, disabling a CRTC/plane is asynchronous, and
-	 * scanout does not actually complete until the next vblank.  So some
-	 * cleanup (like releasing the reference(s) on the backing GEM bo(s))
-	 * should be deferred.  In cases like this, the driver would like to
-	 * hold a ref to the fb even though it has already been removed from
-	 * userspace perspective.
-	 * The refcount is stored inside the mode object.
-	 */
-	/*
-	 * Place on the dev->mode_config.fb_list, access protected by
+	/**
+	 * @head: Place on the dev->mode_config.fb_list, access protected by
 	 * dev->mode_config.fb_lock.
 	 */
 	struct list_head head;
+
+	/**
+	 * @base: base modeset object structure, contains the reference count.
+	 */
 	struct drm_mode_object base;
+	/**
+	 * @funcs: framebuffer vfunc table
+	 */
 	const struct drm_framebuffer_funcs *funcs;
+	/**
+	 * @pitches: Line stride per buffer. For userspace created object this
+	 * is copied from drm_mode_fb_cmd2.
+	 */
 	unsigned int pitches[4];
+	/**
+	 * @offsets: Offset from buffer start to the actual pixel data in bytes,
+	 * per buffer. For userspace created object this is copied from
+	 * drm_mode_fb_cmd2.
+	 *
+	 * Note that this is a linear offset and does not take into account
+	 * tiling or buffer laytou per @modifier. It meant to be used when the
+	 * actual pixel data for this framebuffer plane starts at an offset,
+	 * e.g.  when multiple planes are allocated within the same backing
+	 * storage buffer object. For tiled layouts this generally means it
+	 * @offsets must at least be tile-size aligned, but hardware often has
+	 * stricter requirements.
+	 *
+	 * This should not be used to specifiy x/y pixel offsets into the buffer
+	 * data (even for linear buffers). Specifying an x/y pixel offset is
+	 * instead done through the source rectangle in struct &drm_plane_state.
+	 */
 	unsigned int offsets[4];
+	/**
+	 * @modifier: Data layout modifier, per buffer. This is used to describe
+	 * tiling, or also special layouts (like compression) of auxiliary
+	 * buffers. For userspace created object this is copied from
+	 * drm_mode_fb_cmd2.
+	 */
 	uint64_t modifier[4];
+	/**
+	 * @width: Logical width of the visible area of the framebuffer, in
+	 * pixels.
+	 */
 	unsigned int width;
+	/**
+	 * @height: Logical height of the visible area of the framebuffer, in
+	 * pixels.
+	 */
 	unsigned int height;
-	/* depth can be 15 or 16 */
+	/**
+	 * @depth: Depth in bits per pixel for RGB formats. 0 for everything
+	 * else. Legacy information derived from @pixel_format, it's suggested to use
+	 * the DRM FOURCC codes and helper functions directly instead.
+	 */
 	unsigned int depth;
+	/**
+	 * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for
+	 * everything else. Legacy information derived from @pixel_format, it's
+	 * suggested to use the DRM FOURCC codes and helper functions directly
+	 * instead.
+	 */
 	int bits_per_pixel;
+	/**
+	 * @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
+	 * DRM_MODE_FB_MODIFIERS.
+	 */
 	int flags;
+	/**
+	 * @pixel_format: DRM FOURCC code describing the pixel format.
+	 */
 	uint32_t pixel_format; /* fourcc format */
+	/**
+	 * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
+	 * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
+	 * universal plane.
+	 */
 	int hot_x;
+	/**
+	 * @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor
+	 * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
+	 * universal plane.
+	 */
 	int hot_y;
+	/**
+	 * @filp_head: Placed on struct &drm_file fbs list_head, protected by
+	 * fbs_lock in the same structure.
+	 */
 	struct list_head filp_head;
 };
 
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 13/21] drm: Export drm_property_replace_global_blob
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (10 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 12/21] drm/doc: Update drm_framebuffer docs Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 14/21] drm: Extract drm_connector.[hc] Daniel Vetter
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

It's really part of the core blob interface, and the drm_connector.c
extraction needs it too.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/drm_crtc.c | 13 +++++++------
 include/drm/drm_crtc.h     |  6 ++++++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index daa1e54134ba..1f79f629de52 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3754,12 +3754,12 @@ EXPORT_SYMBOL(drm_property_lookup_blob);
  * a completely atomic update. The access to path_blob_ptr is protected by the
  * caller holding a lock on the connector.
  */
-static int drm_property_replace_global_blob(struct drm_device *dev,
-                                            struct drm_property_blob **replace,
-                                            size_t length,
-                                            const void *data,
-                                            struct drm_mode_object *obj_holds_id,
-                                            struct drm_property *prop_holds_id)
+int drm_property_replace_global_blob(struct drm_device *dev,
+				     struct drm_property_blob **replace,
+				     size_t length,
+				     const void *data,
+				     struct drm_mode_object *obj_holds_id,
+				     struct drm_property *prop_holds_id)
 {
 	struct drm_property_blob *new_blob = NULL;
 	struct drm_property_blob *old_blob = NULL;
@@ -3798,6 +3798,7 @@ err_created:
 	drm_property_unreference_blob(new_blob);
 	return ret;
 }
+EXPORT_SYMBOL(drm_property_replace_global_blob);
 
 /**
  * drm_mode_getblob_ioctl - get the contents of a blob property value
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0119161cad57..f4d041800551 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -2808,6 +2808,12 @@ struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
                                                    const void *data);
 struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
                                                    uint32_t id);
+int drm_property_replace_global_blob(struct drm_device *dev,
+				     struct drm_property_blob **replace,
+				     size_t length,
+				     const void *data,
+				     struct drm_mode_object *obj_holds_id,
+				     struct drm_property *prop_holds_id);
 struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
 void drm_property_unreference_blob(struct drm_property_blob *blob);
 extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 14/21] drm: Extract drm_connector.[hc]
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (11 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 13/21] drm: Export drm_property_replace_global_blob Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-09-21 14:29   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 15/21] drm/doc: Include new drm_blend.c Daniel Vetter
                   ` (7 subsequent siblings)
  20 siblings, 2 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

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.

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
+ * 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;
+	}
+
+	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);
+
+	/* 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 1f79f629de52..07eba82a9998 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.
@@ -580,20 +419,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
@@ -628,312 +453,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;
@@ -1337,39 +856,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,
@@ -1490,225 +981,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
@@ -1890,32 +1162,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;
@@ -1950,133 +1201,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;
@@ -3954,113 +3078,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
@@ -4137,54 +3154,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)
@@ -4266,7 +3235,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);
@@ -4278,22 +3247,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)
 {
@@ -4359,47 +3312,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 f4d041800551..e30ea0be6417 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -39,31 +39,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);
@@ -88,61 +73,6 @@ static inline uint64_t I642U64(int64_t val)
 #define DRM_REFLECT_Y	BIT(5)
 #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
 
-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;
@@ -179,7 +109,6 @@ struct drm_property {
 };
 
 struct drm_crtc;
-struct drm_connector;
 struct drm_encoder;
 struct drm_pending_vblank_event;
 struct drm_plane;
@@ -188,7 +117,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;
 
 /**
@@ -734,291 +662,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.
@@ -1069,8 +712,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
@@ -1111,171 +752,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
@@ -2615,7 +2091,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)
@@ -2661,19 +2136,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,
@@ -2742,23 +2204,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);
@@ -2819,16 +2268,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);
 
@@ -2888,22 +2327,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)
 {
@@ -2931,28 +2354,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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 15/21] drm/doc: Include new drm_blend.c
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (12 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 14/21] drm: Extract drm_connector.[hc] Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 16/21] drm: Don't export dp-aux devnode functions Daniel Vetter
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development
  Cc: Daniel Vetter, Laurent Pinchart, Daniel Vetter, Marek Szyprowski

There's not much point in kerneldoc if it's not included:
- It won't show up in the pretty html pages.
- The comments itself won't get parsed, which means 0day won't pick up
  changes, resulting in stale docs fast.

Also, uapi really should be core, not helpers, so move drm_blend.c to
that. That also means that the zpos normilize function loses it's
helper status (and we might as well call it always). For that,
EXPORT_SYMBOL. Just spotted while integrating docs and noticing that
one was missing.

With sphinx there's really no excuse any more to not build the docs
and make sure it's all nice!

$ make DOCBOOKS="" htmldocs

Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst       | 6 ++++++
 drivers/gpu/drm/Makefile            | 4 ++--
 drivers/gpu/drm/drm_atomic_helper.c | 2 +-
 drivers/gpu/drm/drm_blend.c         | 8 ++++----
 drivers/gpu/drm/drm_crtc_internal.h | 4 ++--
 5 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 449acc2517c7..6e7ab57924f0 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -559,6 +559,12 @@ connector and plane objects by calling the
 pointer to the target object, a pointer to the previously created
 property and an initial instance value.
 
+Blending and Z-Position properties
+----------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_blend.c
+   :export:
+
 Existing KMS Properties
 -----------------------
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 2eff1a33ab63..193ff2d09479 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_connector.o
+		drm_framebuffer.o drm_connector.o drm_blend.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@ -25,7 +25,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
 drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
 		drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
 		drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
-		drm_simple_kms_helper.o drm_blend.o drm_modeset_helper.o
+		drm_simple_kms_helper.o drm_modeset_helper.o
 
 drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
 drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index f59e8c00624f..4d4b0fa7384c 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -594,7 +594,7 @@ drm_atomic_helper_check_planes(struct drm_device *dev,
 	struct drm_plane_state *plane_state;
 	int i, ret = 0;
 
-	ret = drm_atomic_helper_normalize_zpos(dev, state);
+	ret = drm_atomic_normalize_zpos(dev, state);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c
index f3c0942bd756..0813b7e021be 100644
--- a/drivers/gpu/drm/drm_blend.c
+++ b/drivers/gpu/drm/drm_blend.c
@@ -193,8 +193,7 @@ done:
 }
 
 /**
- * drm_atomic_helper_normalize_zpos - calculate normalized zpos values for all
- *				      crtcs
+ * drm_atomic_normalize_zpos - calculate normalized zpos values for all crtcs
  * @dev: DRM device
  * @state: atomic state of DRM device
  *
@@ -205,8 +204,8 @@ done:
  * RETURNS
  * Zero for success or -errno
  */
-int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
-				     struct drm_atomic_state *state)
+int drm_atomic_normalize_zpos(struct drm_device *dev,
+			      struct drm_atomic_state *state)
 {
 	struct drm_crtc *crtc;
 	struct drm_crtc_state *crtc_state;
@@ -236,3 +235,4 @@ int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
 	}
 	return 0;
 }
+EXPORT_SYMBOL(drm_atomic_normalize_zpos);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 7725d0fa7877..97b00312a3cf 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -161,5 +161,5 @@ int drm_modeset_register_all(struct drm_device *dev);
 void drm_modeset_unregister_all(struct drm_device *dev);
 
 /* drm_blend.c */
-int drm_atomic_helper_normalize_zpos(struct drm_device *dev,
-				     struct drm_atomic_state *state);
+int drm_atomic_normalize_zpos(struct drm_device *dev,
+			      struct drm_atomic_state *state);
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 16/21] drm: Don't export dp-aux devnode functions
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (13 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 15/21] drm/doc: Include new drm_blend.c Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 17/21] drm: Update connector documentation Daniel Vetter
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

They're only used internally within the dp helpers. Also nuke the
kerneldoc (we only document the driver interface in the drm shared
functions). And move the header file from the public include/
directory to the source files into drm_crtc_helper_internal.h, similar
to how we already have drm_crtc_internal.h.

While at it also move drm_fb_helper_modinit since that belongs in
there, too.

I noticed this all since I spotted kerneldoc which wasn't pulled into
the rst templates.

v2: Update Copyright date.

Cc: Sean Paul <seanpaul@chromium.org>
Cc: Rafael Antognolli <rafael.antognolli@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_crtc_helper_internal.h | 58 ++++++++++++++++++++++++++++
 drivers/gpu/drm/drm_dp_aux_dev.c           | 19 ++-------
 drivers/gpu/drm/drm_dp_helper.c            |  3 +-
 drivers/gpu/drm/drm_kms_helper_common.c    |  3 +-
 include/drm/drm_dp_aux_dev.h               | 62 ------------------------------
 include/drm/drm_fb_helper.h                |  1 -
 6 files changed, 65 insertions(+), 81 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_crtc_helper_internal.h
 delete mode 100644 include/drm/drm_dp_aux_dev.h

diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h
new file mode 100644
index 000000000000..4e6b57ae7188
--- /dev/null
+++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This header file contains mode setting related functions and definitions
+ * which are only used within the drm kms helper module as internal
+ * implementation details and are not exported to drivers.
+ */
+
+#include <drm/drm_dp_helper.h>
+
+/* drm_fb_helper.c */
+int drm_fb_helper_modinit(void);
+
+/* drm_dp_aux_dev.c */
+#ifdef CONFIG_DRM_DP_AUX_CHARDEV
+int drm_dp_aux_dev_init(void);
+void drm_dp_aux_dev_exit(void);
+int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
+void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
+#else
+static inline int drm_dp_aux_dev_init(void)
+{
+	return 0;
+}
+
+static inline void drm_dp_aux_dev_exit(void)
+{
+}
+
+static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
+{
+	return 0;
+}
+
+static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
+{
+}
+#endif
diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
index 734f86a345f6..ec1ed94b2390 100644
--- a/drivers/gpu/drm/drm_dp_aux_dev.c
+++ b/drivers/gpu/drm/drm_dp_aux_dev.c
@@ -36,6 +36,8 @@
 #include <drm/drm_crtc.h>
 #include <drm/drmP.h>
 
+#include "drm_crtc_helper_internal.h"
+
 struct drm_dp_aux_dev {
 	unsigned index;
 	struct drm_dp_aux *aux;
@@ -283,12 +285,7 @@ static int auxdev_wait_atomic_t(atomic_t *p)
 	schedule();
 	return 0;
 }
-/**
- * drm_dp_aux_unregister_devnode() - unregister a devnode for this aux channel
- * @aux: DisplayPort AUX channel
- *
- * Returns 0 on success or a negative error code on failure.
- */
+
 void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
 {
 	struct drm_dp_aux_dev *aux_dev;
@@ -314,14 +311,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
 	DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name);
 	kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
 }
-EXPORT_SYMBOL(drm_dp_aux_unregister_devnode);
 
-/**
- * drm_dp_aux_register_devnode() - register a devnode for this aux channel
- * @aux: DisplayPort AUX channel
- *
- * Returns 0 on success or a negative error code on failure.
- */
 int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
 {
 	struct drm_dp_aux_dev *aux_dev;
@@ -347,7 +337,6 @@ error:
 	drm_dp_aux_unregister_devnode(aux);
 	return res;
 }
-EXPORT_SYMBOL(drm_dp_aux_register_devnode);
 
 int drm_dp_aux_dev_init(void)
 {
@@ -369,11 +358,9 @@ out:
 	class_destroy(drm_dp_aux_dev_class);
 	return res;
 }
-EXPORT_SYMBOL(drm_dp_aux_dev_init);
 
 void drm_dp_aux_dev_exit(void)
 {
 	unregister_chrdev(drm_dev_major, "aux");
 	class_destroy(drm_dp_aux_dev_class);
 }
-EXPORT_SYMBOL(drm_dp_aux_dev_exit);
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 5d20255f3db3..031c4d335b08 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -28,9 +28,10 @@
 #include <linux/sched.h>
 #include <linux/i2c.h>
 #include <drm/drm_dp_helper.h>
-#include <drm/drm_dp_aux_dev.h>
 #include <drm/drmP.h>
 
+#include "drm_crtc_helper_internal.h"
+
 /**
  * DOC: dp helpers
  *
diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c
index 3187c4bb01cb..45db36cd3d20 100644
--- a/drivers/gpu/drm/drm_kms_helper_common.c
+++ b/drivers/gpu/drm/drm_kms_helper_common.c
@@ -27,7 +27,8 @@
 
 #include <drm/drmP.h>
 #include <drm/drm_fb_helper.h>
-#include <drm/drm_dp_aux_dev.h>
+
+#include "drm_crtc_helper_internal.h"
 
 MODULE_AUTHOR("David Airlie, Jesse Barnes");
 MODULE_DESCRIPTION("DRM KMS helper");
diff --git a/include/drm/drm_dp_aux_dev.h b/include/drm/drm_dp_aux_dev.h
deleted file mode 100644
index 1b76d990d8ab..000000000000
--- a/include/drm/drm_dp_aux_dev.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright © 2015 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- *
- * Authors:
- *    Rafael Antognolli <rafael.antognolli@intel.com>
- *
- */
-
-#ifndef DRM_DP_AUX_DEV
-#define DRM_DP_AUX_DEV
-
-#include <drm/drm_dp_helper.h>
-
-#ifdef CONFIG_DRM_DP_AUX_CHARDEV
-
-int drm_dp_aux_dev_init(void);
-void drm_dp_aux_dev_exit(void);
-int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
-void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
-
-#else
-
-static inline int drm_dp_aux_dev_init(void)
-{
-	return 0;
-}
-
-static inline void drm_dp_aux_dev_exit(void)
-{
-}
-
-static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
-{
-	return 0;
-}
-
-static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
-{
-}
-
-#endif
-
-#endif
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 130c324f1aee..97889a90ff23 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -216,7 +216,6 @@ struct drm_fb_helper {
 };
 
 #ifdef CONFIG_DRM_FBDEV_EMULATION
-int drm_fb_helper_modinit(void);
 void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
 			   const struct drm_fb_helper_funcs *funcs);
 int drm_fb_helper_init(struct drm_device *dev,
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 17/21] drm: Update connector documentation
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (14 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 16/21] drm: Don't export dp-aux devnode functions Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 18/21] drm: Remove display_info->min/max_(h|v)max Daniel Vetter
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

- Shuffle docs from drm-kms.rst into the structure docs where it makes
  sense.
- Put the remaining bits into a new overview section.

One thing I've changed is around probing: Old docs says that you
_must_ use the probe helpers, which isn't correct. Helpers are always
optional.

v2: Review from Sean.

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/drm-kms.rst   | 170 ++--------------------------------------
 drivers/gpu/drm/drm_connector.c |  33 +++++++-
 include/drm/drm_connector.h     |  57 +++++++++++++-
 3 files changed, 94 insertions(+), 166 deletions(-)

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 6e7ab57924f0..fa948b4e029b 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -110,8 +110,14 @@ Display Modes Function Reference
 .. kernel-doc:: drivers/gpu/drm/drm_modes.c
    :export:
 
-Connector Display Sink Abstraction
-==================================
+Connector Abstraction
+=====================
+
+.. kernel-doc:: drivers/gpu/drm/drm_connector.c
+   :doc: overview
+
+Connector Functions Reference
+-----------------------------
 
 .. kernel-doc:: include/drm/drm_connector.h
    :internal:
@@ -232,166 +238,6 @@ encoders unattached at initialization time. Applications (or the fbdev
 compatibility layer when implemented) are responsible for attaching the
 encoders they want to use to a CRTC.
 
-Connectors (:c:type:`struct drm_connector <drm_connector>`)
------------------------------------------------------------
-
-A connector is the final destination for pixel data on a device, and
-usually connects directly to an external display device like a monitor
-or laptop panel. A connector can only be attached to one encoder at a
-time. The connector is also the structure where information about the
-attached display is kept, so it contains fields for display data, EDID
-data, DPMS & connection status, and information about modes supported on
-the attached displays.
-
-Connector Initialization
-~~~~~~~~~~~~~~~~~~~~~~~~
-
-Finally a KMS driver must create, initialize, register and attach at
-least one :c:type:`struct drm_connector <drm_connector>`
-instance. The instance is created as other KMS objects and initialized
-by setting the following fields.
-
-interlace_allowed
-    Whether the connector can handle interlaced modes.
-
-doublescan_allowed
-    Whether the connector can handle doublescan.
-
-display_info
-    Display information is filled from EDID information when a display
-    is detected. For non hot-pluggable displays such as flat panels in
-    embedded systems, the driver should initialize the
-    display_info.width_mm and display_info.height_mm fields with the
-    physical size of the display.
-
-polled
-    Connector polling mode, a combination of
-
-    DRM_CONNECTOR_POLL_HPD
-        The connector generates hotplug events and doesn't need to be
-        periodically polled. The CONNECT and DISCONNECT flags must not
-        be set together with the HPD flag.
-
-    DRM_CONNECTOR_POLL_CONNECT
-        Periodically poll the connector for connection.
-
-    DRM_CONNECTOR_POLL_DISCONNECT
-        Periodically poll the connector for disconnection.
-
-    Set to 0 for connectors that don't support connection status
-    discovery.
-
-The connector is then registered with a call to
-:c:func:`drm_connector_init()` with a pointer to the connector
-functions and a connector type, and exposed through sysfs with a call to
-:c:func:`drm_connector_register()`.
-
-Supported connector types are
-
--  DRM_MODE_CONNECTOR_VGA
--  DRM_MODE_CONNECTOR_DVII
--  DRM_MODE_CONNECTOR_DVID
--  DRM_MODE_CONNECTOR_DVIA
--  DRM_MODE_CONNECTOR_Composite
--  DRM_MODE_CONNECTOR_SVIDEO
--  DRM_MODE_CONNECTOR_LVDS
--  DRM_MODE_CONNECTOR_Component
--  DRM_MODE_CONNECTOR_9PinDIN
--  DRM_MODE_CONNECTOR_DisplayPort
--  DRM_MODE_CONNECTOR_HDMIA
--  DRM_MODE_CONNECTOR_HDMIB
--  DRM_MODE_CONNECTOR_TV
--  DRM_MODE_CONNECTOR_eDP
--  DRM_MODE_CONNECTOR_VIRTUAL
-
-Connectors must be attached to an encoder to be used. For devices that
-map connectors to encoders 1:1, the connector should be attached at
-initialization time with a call to
-:c:func:`drm_mode_connector_attach_encoder()`. The driver must
-also set the :c:type:`struct drm_connector <drm_connector>`
-encoder field to point to the attached encoder.
-
-Finally, drivers must initialize the connectors state change detection
-with a call to :c:func:`drm_kms_helper_poll_init()`. If at least
-one connector is pollable but can't generate hotplug interrupts
-(indicated by the DRM_CONNECTOR_POLL_CONNECT and
-DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will
-automatically be queued to periodically poll for changes. Connectors
-that can generate hotplug interrupts must be marked with the
-DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must
-call :c:func:`drm_helper_hpd_irq_event()`. The function will
-queue a delayed work to check the state of all connectors, but no
-periodic polling will be done.
-
-Connector Operations
-~~~~~~~~~~~~~~~~~~~~
-
-    **Note**
-
-    Unless otherwise state, all operations are mandatory.
-
-DPMS
-''''
-
-void (\*dpms)(struct drm_connector \*connector, int mode);
-The DPMS operation sets the power state of a connector. The mode
-argument is one of
-
--  DRM_MODE_DPMS_ON
-
--  DRM_MODE_DPMS_STANDBY
-
--  DRM_MODE_DPMS_SUSPEND
-
--  DRM_MODE_DPMS_OFF
-
-In all but DPMS_ON mode the encoder to which the connector is attached
-should put the display in low-power mode by driving its signals
-appropriately. If more than one connector is attached to the encoder
-care should be taken not to change the power state of other displays as
-a side effect. Low-power mode should be propagated to the encoders and
-CRTCs when all related connectors are put in low-power mode.
-
-Modes
-'''''
-
-int (\*fill_modes)(struct drm_connector \*connector, uint32_t
-max_width, uint32_t max_height);
-Fill the mode list with all supported modes for the connector. If the
-``max_width`` and ``max_height`` arguments are non-zero, the
-implementation must ignore all modes wider than ``max_width`` or higher
-than ``max_height``.
-
-The connector must also fill in this operation its display_info
-width_mm and height_mm fields with the connected display physical size
-in millimeters. The fields should be set to 0 if the value isn't known
-or is not applicable (for instance for projector devices).
-
-Connection Status
-'''''''''''''''''
-
-The connection status is updated through polling or hotplug events when
-supported (see ?). The status value is reported to userspace through
-ioctls and must not be used inside the driver, as it only gets
-initialized by a call to :c:func:`drm_mode_getconnector()` from
-userspace.
-
-enum drm_connector_status (\*detect)(struct drm_connector
-\*connector, bool force);
-Check to see if anything is attached to the connector. The ``force``
-parameter is set to false whilst polling or to true when checking the
-connector due to user request. ``force`` can be used by the driver to
-avoid expensive, destructive operations during automated probing.
-
-Return connector_status_connected if something is connected to the
-connector, connector_status_disconnected if nothing is connected and
-connector_status_unknown if the connection state isn't known.
-
-Drivers should only return connector_status_connected if the
-connection status has really been probed as connected. Connectors that
-can't detect the connection status, or failed connection status probes,
-should return connector_status_unknown.
-
 Cleanup
 -------
 
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 99ece6758061..6a0551744d13 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -27,6 +27,37 @@
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
+/**
+ * DOC: overview
+ *
+ * In DRM connectors are the general abstraction for display sinks, and include
+ * als fixed panels or anything else that can display pixels in some form. As
+ * opposed to all other KMS objects representing hardware (like CRTC, encoder or
+ * plane abstractions) connectors can be hotplugged and unplugged at runtime.
+ * Hence they are reference-counted using drm_connector_reference() and
+ * drm_connector_unreference().
+ *
+ * KMS driver must create, initialize, register and attach at a struct
+ * &drm_connector for each such sink. The instance is created as other KMS
+ * objects and initialized by setting the following fields.
+ *
+ * The connector is then registered with a call to drm_connector_init() with a
+ * pointer to the connector functions and a connector type, and exposed through
+ * sysfs with a call to drm_connector_register().
+ *
+ * Connectors must be attached to an encoder to be used. For devices that map
+ * connectors to encoders 1:1, the connector should be attached at
+ * initialization time with a call to drm_mode_connector_attach_encoder(). The
+ * driver must also set the struct &drm_connector encoder field to point to the
+ * attached encoder.
+ *
+ * For connectors which are not fixed (like built-in panels) the driver needs to
+ * support hotplug notifications. The simplest way to do that is by using the
+ * probe helpers, see drm_kms_helper_poll_init() for connectors which don't have
+ * hardware support for hotplug interrupts. Connectors with hardware hotplug
+ * support can instead use e.g. drm_helper_hpd_irq_event().
+ */
+
 struct drm_conn_prop_enum_list {
 	int type;
 	const char *name;
@@ -77,7 +108,7 @@ void drm_connector_ida_destroy(void)
  * 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
+ * The kernel supports per-connector configuration 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
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ec2bea0b1b38..3537b7d8259b 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -42,9 +42,36 @@ enum drm_connector_force {
 	DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
 };
 
+/**
+ * enum drm_connector_status - status for a &drm_connector
+ *
+ * This enum is used to track the connector status. There are no separate
+ * #defines for the uapi!
+ */
 enum drm_connector_status {
+	/**
+	 * @connector_status_connected: The connector is definitely connected to
+	 * a sink device, and can be enabled.
+	 */
 	connector_status_connected = 1,
+	/**
+	 * @connector_status_disconnected: The connector isn't connected to a
+	 * sink device which can be autodetect. For digital outputs like DP or
+	 * HDMI (which can be realiable probed) this means there's really
+	 * nothing there. It is driver-dependent whether a connector with this
+	 * status can be lit up or not.
+	 */
 	connector_status_disconnected = 2,
+	/**
+	 * @connector_status_unknown: The connector's status could not be
+	 * reliably detected. This happens when probing would either cause
+	 * flicker (like load-detection when the connector is in use), or when a
+	 * hardware resource isn't available (like when load-detection needs a
+	 * free CRTC). It should be possible to light up the connector with one
+	 * of the listed fallback modes. For default configuration userspace
+	 * should only try to light up connectors with unknown status when
+	 * there's not connector with @connector_status_connected.
+	 */
 	connector_status_unknown = 3,
 };
 
@@ -416,11 +443,9 @@ struct drm_cmdline_mode {
  * @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
@@ -485,6 +510,13 @@ struct drm_connector {
 	/* these are modes added by probing with DDC or the BIOS */
 	struct list_head probed_modes;
 
+	/**
+	 * @display_info: Display information is filled from EDID information
+	 * when a display is detected. For non hot-pluggable displays such as
+	 * flat panels in embedded systems, the driver should initialize the
+	 * display_info.width_mm and display_info.height_mm fields with the
+	 * physical size of the display.
+	 */
 	struct drm_display_info display_info;
 	const struct drm_connector_funcs *funcs;
 
@@ -519,7 +551,26 @@ struct drm_connector {
 /* DACs should rarely do this without a lot of testing */
 #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
 
-	uint8_t polled; /* DRM_CONNECTOR_POLL_* */
+	/**
+	 * @polled:
+	 *
+	 * Connector polling mode, a combination of
+	 *
+	 * DRM_CONNECTOR_POLL_HPD
+	 *     The connector generates hotplug events and doesn't need to be
+	 *     periodically polled. The CONNECT and DISCONNECT flags must not
+	 *     be set together with the HPD flag.
+	 *
+	 * DRM_CONNECTOR_POLL_CONNECT
+	 *     Periodically poll the connector for connection.
+	 *
+	 * DRM_CONNECTOR_POLL_DISCONNECT
+	 *     Periodically poll the connector for disconnection.
+	 *
+	 * Set to 0 for connectors that don't support connection status
+	 * discovery.
+	 */
+	uint8_t polled;
 
 	/* requested DPMS state */
 	int dpms;
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 18/21] drm: Remove display_info->min/max_(h|v)max
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (15 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 17/21] drm: Update connector documentation Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-12 20:48 ` [PATCH 19/21] drm: document drm_display_info Daniel Vetter
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

No one looks at it, only i915/gma500 lvds even bother to fill it
out. I guess a very old plan was to use this for filtering modes,
but that's already done within the edid parser.

v2: Move misplaced hunk to this patch.

Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 drivers/gpu/drm/gma500/cdv_intel_lvds.c   |  8 --------
 drivers/gpu/drm/gma500/mdfld_dsi_output.c |  5 -----
 drivers/gpu/drm/gma500/psb_intel_lvds.c   |  9 ---------
 drivers/gpu/drm/i915/intel_lvds.c         | 11 -----------
 include/drm/drm_connector.h               |  3 ---
 5 files changed, 36 deletions(-)

diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 38dc89083148..ea733ab5b1e0 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -415,14 +415,6 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
 	if (ret)
 		return ret;
 
-	/* Didn't get an EDID, so
-	 * Set wide sync ranges so we get all modes
-	 * handed to valid_mode for checking
-	 */
-	connector->display_info.min_vfreq = 0;
-	connector->display_info.max_vfreq = 200;
-	connector->display_info.min_hfreq = 0;
-	connector->display_info.max_hfreq = 200;
 	if (mode_dev->panel_fixed_mode != NULL) {
 		struct drm_display_mode *mode =
 		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 907cb51795c3..acb3848ef1c9 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -335,11 +335,6 @@ static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
 	struct drm_display_mode *dup_mode = NULL;
 	struct drm_device *dev = connector->dev;
 
-	connector->display_info.min_vfreq = 0;
-	connector->display_info.max_vfreq = 200;
-	connector->display_info.min_hfreq = 0;
-	connector->display_info.max_hfreq = 200;
-
 	if (fixed_mode) {
 		dev_dbg(dev->dev, "fixed_mode %dx%d\n",
 				fixed_mode->hdisplay, fixed_mode->vdisplay);
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index e55733ca46d2..fd7c91254841 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -530,15 +530,6 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
 	if (ret)
 		return ret;
 
-	/* Didn't get an EDID, so
-	 * Set wide sync ranges so we get all modes
-	 * handed to valid_mode for checking
-	 */
-	connector->display_info.min_vfreq = 0;
-	connector->display_info.max_vfreq = 200;
-	connector->display_info.min_hfreq = 0;
-	connector->display_info.max_hfreq = 200;
-
 	if (mode_dev->panel_fixed_mode != NULL) {
 		struct drm_display_mode *mode =
 		    drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 668eabb0ba1b..52d6ed6f6966 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -1113,17 +1113,6 @@ void intel_lvds_init(struct drm_device *dev)
 	}
 	lvds_connector->base.edid = edid;
 
-	if (IS_ERR_OR_NULL(edid)) {
-		/* Didn't get an EDID, so
-		 * Set wide sync ranges so we get all modes
-		 * handed to valid_mode for checking
-		 */
-		connector->display_info.min_vfreq = 0;
-		connector->display_info.max_vfreq = 200;
-		connector->display_info.min_hfreq = 0;
-		connector->display_info.max_hfreq = 200;
-	}
-
 	list_for_each_entry(scan, &connector->probed_modes, head) {
 		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
 			DRM_DEBUG_KMS("using preferred mode from EDID: ");
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 3537b7d8259b..bc88a5575792 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -94,9 +94,6 @@ struct drm_display_info {
         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;
 
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 19/21] drm: document drm_display_info
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (16 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 18/21] drm: Remove display_info->min/max_(h|v)max Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc Daniel Vetter
                   ` (2 subsequent siblings)
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

We seem to have a bit a mess in how to describe the bus formats, with
a multitude of competing ways. Might be best to consolidate it all and
use MEDIA_BUS_FMT_ also for the hdmi color formats and high color
modes.

Also move all the display_info related functions into drm_connector.c
(there's only one) to group it all together. I did decided against
also moving the edid related display info functions, they seem to fit
better in drm_edid.c. Instead sprinkle a few cross references around.
While at that reduce the kerneldoc for static functions, there's not
point in documenting internals with that much detail really.

v2: Fix typo and move misplaced hunk (Sean).

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_connector.c | 34 ++++++++++++++++++++++
 drivers/gpu/drm/drm_crtc.c      | 34 ----------------------
 drivers/gpu/drm/drm_edid.c      | 23 +++------------
 include/drm/drm_connector.h     | 63 ++++++++++++++++++++++++++++++++++++++---
 include/drm/drm_crtc.h          |  4 ---
 5 files changed, 97 insertions(+), 61 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 6a0551744d13..26bb78c76481 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -506,6 +506,40 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
 };
 DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
 
+/**
+ * drm_display_info_set_bus_formats - set the supported bus formats
+ * @info: display info to store bus formats in
+ * @formats: array containing the supported bus formats
+ * @num_formats: the number of entries in the fmts array
+ *
+ * Store the supported bus formats in display info structure.
+ * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for
+ * a full list of available formats.
+ */
+int drm_display_info_set_bus_formats(struct drm_display_info *info,
+				     const u32 *formats,
+				     unsigned int num_formats)
+{
+	u32 *fmts = NULL;
+
+	if (!formats && num_formats)
+		return -EINVAL;
+
+	if (formats && num_formats) {
+		fmts = kmemdup(formats, sizeof(*formats) * num_formats,
+			       GFP_KERNEL);
+		if (!fmts)
+			return -ENOMEM;
+	}
+
+	kfree(info->bus_formats);
+	info->bus_formats = fmts;
+	info->num_bus_formats = num_formats;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_display_info_set_bus_formats);
+
 /* Optional connector properties. */
 static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
 	{ DRM_MODE_SCALE_NONE, "None" },
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 07eba82a9998..d228c41b572b 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -419,40 +419,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
 
-/**
- * drm_display_info_set_bus_formats - set the supported bus formats
- * @info: display info to store bus formats in
- * @formats: array containing the supported bus formats
- * @num_formats: the number of entries in the fmts array
- *
- * Store the supported bus formats in display info structure.
- * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for
- * a full list of available formats.
- */
-int drm_display_info_set_bus_formats(struct drm_display_info *info,
-				     const u32 *formats,
-				     unsigned int num_formats)
-{
-	u32 *fmts = NULL;
-
-	if (!formats && num_formats)
-		return -EINVAL;
-
-	if (formats && num_formats) {
-		fmts = kmemdup(formats, sizeof(*formats) * num_formats,
-			       GFP_KERNEL);
-		if (!fmts)
-			return -ENOMEM;
-	}
-
-	kfree(info->bus_formats);
-	info->bus_formats = fmts;
-	info->num_bus_formats = num_formats;
-
-	return 0;
-}
-EXPORT_SYMBOL(drm_display_info_set_bus_formats);
-
 static int drm_encoder_register_all(struct drm_device *dev)
 {
 	struct drm_encoder *encoder;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index c071bd635160..9b1ec64d579a 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3732,14 +3732,7 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
 }
 EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
 
-/**
- * drm_assign_hdmi_deep_color_info - detect whether monitor supports
- * hdmi deep color modes and update drm_display_info if so.
- * @edid: monitor EDID information
- * @info: Updated with maximum supported deep color bpc and color format
- *        if deep color supported.
- * @connector: DRM connector, used only for debug output
- *
+/*
  * Parse the CEA extension according to CEA-861-B.
  * Return true if HDMI deep color supported, false if not or unknown.
  */
@@ -3833,16 +3826,6 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
 	return false;
 }
 
-/**
- * drm_add_display_info - pull display info out if present
- * @edid: EDID data
- * @info: display info (attached to connector)
- * @connector: connector whose edid is used to build display info
- *
- * Grab any available display info and stuff it into the drm_display_info
- * structure that's part of the connector.  Useful for tracking bpp and
- * color spaces.
- */
 static void drm_add_display_info(struct edid *edid,
                                  struct drm_display_info *info,
                                  struct drm_connector *connector)
@@ -4063,7 +4046,9 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
  * @connector: connector we're probing
  * @edid: EDID data
  *
- * Add the specified modes to the connector's mode list.
+ * Add the specified modes to the connector's mode list. Also fills out the
+ * &drm_display_info structure in @connector with any information which can be
+ * derived from the edid.
  *
  * Return: The number of modes added or 0 if we couldn't find any.
  */
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index bc88a5575792..f1576db6c044 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -84,28 +84,69 @@ enum subpixel_order {
 	SubPixelNone,
 };
 
-/*
- * Describes a given display (e.g. CRT or flat panel) and its limitations.
+/**
+ * struct drm_display_info - runtime data about the connected sink
+ *
+ * Describes a given display (e.g. CRT or flat panel) and its limitations. For
+ * fixed display sinks like built-in panels there's not much difference between
+ * this and struct &drm_connector. But for sinks with a real cable this
+ * structure is meant to describe all the things at the other end of the cable.
+ *
+ * For sinks which provide an EDID this can be filled out by calling
+ * drm_add_edid_modes().
  */
 struct drm_display_info {
+	/**
+	 * @name: Name of the display.
+	 */
 	char name[DRM_DISPLAY_INFO_LEN];
 
-	/* Physical size */
+	/**
+	 * @width_mm: Physical width in mm.
+	 */
         unsigned int width_mm;
+	/**
+	 * @height_mm: Physical height in mm.
+	 */
 	unsigned int height_mm;
 
+	/**
+	 * @pixel_clock: Maximum pixel clock supported by the sink, in units of
+	 * 100Hz. This mismatches the clok in &drm_display_mode (which is in
+	 * kHZ), because that's what the EDID uses as base unit.
+	 */
 	unsigned int pixel_clock;
+	/**
+	 * @bpc: Maximum bits per color channel. Used by HDMI and DP outputs.
+	 */
 	unsigned int bpc;
 
+	/**
+	 * @subpixel_order: Subpixel order of LCD panels.
+	 */
 	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)
 
+	/**
+	 * @color_formats: HDMI Color formats, selects between RGB and YCrCb
+	 * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones
+	 * as used to describe the pixel format in framebuffers, and also don't
+	 * match the formats in @bus_formats which are shared with v4l.
+	 */
 	u32 color_formats;
 
+	/**
+	 * @bus_formats: Pixel data format on the wire, somewhat redundant with
+	 * @color_formats. Array of size @num_bus_formats encoded using
+	 * MEDIA_BUS_FMT\_ defines shared with v4l and media drivers.
+	 */
 	const u32 *bus_formats;
+	/**
+	 * @num_bus_formats: Size of @bus_formats array.
+	 */
 	unsigned int num_bus_formats;
 
 #define DRM_BUS_FLAG_DE_LOW		(1<<0)
@@ -115,14 +156,28 @@ struct drm_display_info {
 /* drive data on neg. edge */
 #define DRM_BUS_FLAG_PIXDATA_NEGEDGE	(1<<3)
 
+	/**
+	 * @bus_flags: Additional information (like pixel signal polarity) for
+	 * the pixel data on the bus, using DRM_BUS_FLAGS\_ defines.
+	 */
 	u32 bus_flags;
 
-	/* Mask of supported hdmi deep color modes */
+	/**
+	 * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
+	 * more stuff redundant with @bus_formats.
+	 */
 	u8 edid_hdmi_dc_modes;
 
+	/**
+	 * @cea_rev: CEA revision of the HDMI sink.
+	 */
 	u8 cea_rev;
 };
 
+int drm_display_info_set_bus_formats(struct drm_display_info *info,
+				     const u32 *formats,
+				     unsigned int num_formats);
+
 /**
  * struct drm_connector_state - mutable connector state
  * @connector: backpointer to the connector
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index e30ea0be6417..3fa0275e509f 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -2208,10 +2208,6 @@ 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_display_info_set_bus_formats(struct drm_display_info *info,
-					    const u32 *formats,
-					    unsigned int num_formats);
-
 static inline bool drm_property_type_is(struct drm_property *property,
 		uint32_t type)
 {
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (17 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 19/21] drm: document drm_display_info Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
  2016-08-12 20:48 ` [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c Daniel Vetter
  2016-08-16 13:42 ` [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Sean Paul
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter, linux-doc, Jonathan Corbet

Move the documentation into Documentation/gpu, link it up and pull in
the kernel doc.

No actual text changes except that I did polish the kerneldoc a bit,
especially for vga_client_register().

v2: Remove some rst from vga-switcheroo.rst that I don't understand,
but which seems to be the reason why the new vgaarbiter.rst sometimes
drops out of the sidebar index.

v3: Drop one level of headings and clarify the vgaarb one a bit.

v4: Fix some typos (Sean).

Cc: Jonathan Corbet <corbet@lwn.net>
Cc: linux-doc@vger.kernel.org
Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 Documentation/gpu/index.rst          |   1 +
 Documentation/gpu/vga-switcheroo.rst |   2 -
 Documentation/gpu/vgaarbiter.rst     | 191 ++++++++++++++++++++++++++++++++++
 Documentation/vgaarbiter.txt         | 192 -----------------------------------
 drivers/gpu/vga/vgaarb.c             | 110 +++++++++++++++++++-
 include/linux/vgaarb.h               | 128 +++--------------------
 6 files changed, 316 insertions(+), 308 deletions(-)
 create mode 100644 Documentation/gpu/vgaarbiter.rst
 delete mode 100644 Documentation/vgaarbiter.txt

diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
index fcac0fa72056..ba92f45abb76 100644
--- a/Documentation/gpu/index.rst
+++ b/Documentation/gpu/index.rst
@@ -12,3 +12,4 @@ Linux GPU Driver Developer's Guide
    drm-uapi
    i915
    vga-switcheroo
+   vgaarbiter
diff --git a/Documentation/gpu/vga-switcheroo.rst b/Documentation/gpu/vga-switcheroo.rst
index cbbdb994f1dd..463a74fc40d1 100644
--- a/Documentation/gpu/vga-switcheroo.rst
+++ b/Documentation/gpu/vga-switcheroo.rst
@@ -1,5 +1,3 @@
-.. _vga_switcheroo:
-
 ==============
 VGA Switcheroo
 ==============
diff --git a/Documentation/gpu/vgaarbiter.rst b/Documentation/gpu/vgaarbiter.rst
new file mode 100644
index 000000000000..0b41b051d021
--- /dev/null
+++ b/Documentation/gpu/vgaarbiter.rst
@@ -0,0 +1,191 @@
+===========
+VGA Arbiter
+===========
+
+Graphic devices are accessed through ranges in I/O or memory space. While most
+modern devices allow relocation of such ranges, some "Legacy" VGA devices
+implemented on PCI will typically have the same "hard-decoded" addresses as
+they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
+Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
+Section 7, Legacy Devices.
+
+The Resource Access Control (RAC) module inside the X server [0] existed for
+the legacy VGA arbitration task (besides other bus management tasks) when more
+than one legacy device co-exists on the same machine. But the problem happens
+when these devices are trying to be accessed by different userspace clients
+(e.g. two server in parallel). Their address assignments conflict. Moreover,
+ideally, being a userspace application, it is not the role of the X server to
+control bus resources. Therefore an arbitration scheme outside of the X server
+is needed to control the sharing of these resources. This document introduces
+the operation of the VGA arbiter implemented for the Linux kernel.
+
+vgaarb kernel/userspace ABI
+---------------------------
+
+The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
+scans all PCI devices and adds the VGA ones inside the arbitration. The
+arbiter then enables/disables the decoding on different devices of the VGA
+legacy instructions. Devices which do not want/need to use the arbiter may
+explicitly tell it by calling vga_set_legacy_decoding().
+
+The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
+which has the following semantics:
+
+open
+        Opens a user instance of the arbiter. By default, it's attached to the
+        default VGA device of the system.
+
+close
+        Close a user instance. Release locks made by the user
+
+read
+        Return a string indicating the status of the target like:
+
+        "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
+
+        An IO state string is of the form {io,mem,io+mem,none}, mc and
+        ic are respectively mem and io lock counts (for debugging/
+        diagnostic only). "decodes" indicate what the card currently
+        decodes, "owns" indicates what is currently enabled on it, and
+        "locks" indicates what is locked by this card. If the card is
+        unplugged, we get "invalid" then for card_ID and an -ENODEV
+        error is returned for any command until a new card is targeted.
+
+
+write
+        Write a command to the arbiter. List of commands:
+
+        target <card_ID>
+                switch target to card <card_ID> (see below)
+        lock <io_state>
+                acquires locks on target ("none" is an invalid io_state)
+        trylock <io_state>
+                non-blocking acquire locks on target (returns EBUSY if
+                unsuccessful)
+        unlock <io_state>
+                release locks on target
+        unlock all
+                release all locks on target held by this user (not implemented
+                yet)
+        decodes <io_state>
+                set the legacy decoding attributes for the card
+
+        poll
+                event if something changes on any card (not just the target)
+
+        card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
+        to go back to the system default card (TODO: not implemented yet). Currently,
+        only PCI is supported as a prefix, but the userland API may support other bus
+        types in the future, even if the current kernel implementation doesn't.
+
+Note about locks:
+
+The driver keeps track of which user has which locks on which card. It
+supports stacking, like the kernel one. This complexifies the implementation
+a bit, but makes the arbiter more tolerant to user space problems and able
+to properly cleanup in all cases when a process dies.
+Currently, a max of 16 cards can have locks simultaneously issued from
+user space for a given user (file descriptor instance) of the arbiter.
+
+In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
+notify them being added/removed in the system and automatically added/removed
+in the arbiter.
+
+There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
+drivers want to use it.
+
+In-kernel interface
+-------------------
+
+.. kernel-doc:: include/linux/vgaarb.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/vga/vgaarb.c
+   :export:
+
+libpciaccess
+------------
+
+To use the vga arbiter char device it was implemented an API inside the
+libpciaccess library. One field was added to struct pci_device (each device
+on the system)::
+
+    /* the type of resource decoded by the device */
+    int vgaarb_rsrc;
+
+Besides it, in pci_system were added::
+
+    int vgaarb_fd;
+    int vga_count;
+    struct pci_device *vga_target;
+    struct pci_device *vga_default_dev;
+
+The vga_count is used to track how many cards are being arbitrated, so for
+instance, if there is only one card, then it can completely escape arbitration.
+
+These functions below acquire VGA resources for the given card and mark those
+resources as locked. If the resources requested are "normal" (and not legacy)
+resources, the arbiter will first check whether the card is doing legacy
+decoding for that type of resource. If yes, the lock is "converted" into a
+legacy resource lock. The arbiter will first look for all VGA cards that
+might conflict and disable their IOs and/or Memory access, including VGA
+forwarding on P2P bridges if necessary, so that the requested resources can
+be used. Then, the card is marked as locking these resources and the IO and/or
+Memory access is enabled on the card (including VGA forwarding on parent
+P2P bridges if any). In the case of vga_arb_lock(), the function will block
+if some conflicting card is already locking one of the required resources (or
+any resource on a different bus segment, since P2P bridges don't differentiate
+VGA memory and IO afaik). If the card already owns the resources, the function
+succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
+calls are supported (a per-resource counter is maintained).
+
+Set the target device of this client. ::
+
+    int  pci_device_vgaarb_set_target   (struct pci_device *dev);
+
+For instance, in x86 if two devices on the same bus want to lock different
+resources, both will succeed (lock). If devices are in different buses and
+trying to lock different resources, only the first who tried succeeds. ::
+
+    int  pci_device_vgaarb_lock         (void);
+    int  pci_device_vgaarb_trylock      (void);
+
+Unlock resources of device. ::
+
+    int  pci_device_vgaarb_unlock       (void);
+
+Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
+Memory, both, or none. All cards default to both, the card driver (fbdev for
+example) should tell the arbiter if it has disabled legacy decoding, so the
+card can be left out of the arbitration process (and can be safe to take
+interrupts at any time. ::
+
+    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);
+
+Connects to the arbiter device, allocates the struct ::
+
+    int  pci_device_vgaarb_init         (void);
+
+Close the connection ::
+
+    void pci_device_vgaarb_fini         (void);
+
+xf86VGAArbiter (X server implementation)
+----------------------------------------
+
+X server basically wraps all the functions that touch VGA registers somehow.
+
+References
+----------
+
+Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
+with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
+Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
+enhancing the kernel code to adapt as a kernel module and also did the
+implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
+Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
+
+0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
+1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
+2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
+3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
diff --git a/Documentation/vgaarbiter.txt b/Documentation/vgaarbiter.txt
deleted file mode 100644
index 014423e2824c..000000000000
--- a/Documentation/vgaarbiter.txt
+++ /dev/null
@@ -1,192 +0,0 @@
-
-VGA Arbiter
-===========
-
-Graphic devices are accessed through ranges in I/O or memory space. While most
-modern devices allow relocation of such ranges, some "Legacy" VGA devices
-implemented on PCI will typically have the same "hard-decoded" addresses as
-they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
-Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
-Section 7, Legacy Devices.
-
-The Resource Access Control (RAC) module inside the X server [0] existed for
-the legacy VGA arbitration task (besides other bus management tasks) when more
-than one legacy device co-exists on the same machine. But the problem happens
-when these devices are trying to be accessed by different userspace clients
-(e.g. two server in parallel). Their address assignments conflict. Moreover,
-ideally, being a userspace application, it is not the role of the X server to
-control bus resources. Therefore an arbitration scheme outside of the X server
-is needed to control the sharing of these resources. This document introduces
-the operation of the VGA arbiter implemented for the Linux kernel.
-
-----------------------------------------------------------------------------
-
-I.  Details and Theory of Operation
-        I.1 vgaarb
-        I.2 libpciaccess
-        I.3 xf86VGAArbiter (X server implementation)
-II. Credits
-III.References
-
-
-I. Details and Theory of Operation
-==================================
-
-I.1 vgaarb
-----------
-
-The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
-scans all PCI devices and adds the VGA ones inside the arbitration. The
-arbiter then enables/disables the decoding on different devices of the VGA
-legacy instructions. Devices which do not want/need to use the arbiter may
-explicitly tell it by calling vga_set_legacy_decoding().
-
-The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
-which has the following semantics:
-
- open       : open user instance of the arbiter. By default, it's attached to
-              the default VGA device of the system.
-
- close      : close user instance. Release locks made by the user
-
- read       : return a string indicating the status of the target like:
-
-              "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
-
-              An IO state string is of the form {io,mem,io+mem,none}, mc and
-              ic are respectively mem and io lock counts (for debugging/
-              diagnostic only). "decodes" indicate what the card currently
-              decodes, "owns" indicates what is currently enabled on it, and
-              "locks" indicates what is locked by this card. If the card is
-              unplugged, we get "invalid" then for card_ID and an -ENODEV
-              error is returned for any command until a new card is targeted.
-
-
- write       : write a command to the arbiter. List of commands:
-
-  target <card_ID>   : switch target to card <card_ID> (see below)
-  lock <io_state>    : acquires locks on target ("none" is an invalid io_state)
-  trylock <io_state> : non-blocking acquire locks on target (returns EBUSY if
-                       unsuccessful)
-  unlock <io_state>  : release locks on target
-  unlock all         : release all locks on target held by this user (not
-                       implemented yet)
-  decodes <io_state> : set the legacy decoding attributes for the card
-
-  poll               : event if something changes on any card (not just the
-                       target)
-
-  card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
-  to go back to the system default card (TODO: not implemented yet). Currently,
-  only PCI is supported as a prefix, but the userland API may support other bus
-  types in the future, even if the current kernel implementation doesn't.
-
-Note about locks:
-
-The driver keeps track of which user has which locks on which card. It
-supports stacking, like the kernel one. This complexifies the implementation
-a bit, but makes the arbiter more tolerant to user space problems and able
-to properly cleanup in all cases when a process dies.
-Currently, a max of 16 cards can have locks simultaneously issued from
-user space for a given user (file descriptor instance) of the arbiter.
-
-In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
-notify them being added/removed in the system and automatically added/removed
-in the arbiter.
-
-There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
-drivers want to use it.
-
-
-I.2 libpciaccess
-----------------
-
-To use the vga arbiter char device it was implemented an API inside the
-libpciaccess library. One field was added to struct pci_device (each device
-on the system):
-
-    /* the type of resource decoded by the device */
-    int vgaarb_rsrc;
-
-Besides it, in pci_system were added:
-
-    int vgaarb_fd;
-    int vga_count;
-    struct pci_device *vga_target;
-    struct pci_device *vga_default_dev;
-
-
-The vga_count is used to track how many cards are being arbitrated, so for
-instance, if there is only one card, then it can completely escape arbitration.
-
-
-These functions below acquire VGA resources for the given card and mark those
-resources as locked. If the resources requested are "normal" (and not legacy)
-resources, the arbiter will first check whether the card is doing legacy
-decoding for that type of resource. If yes, the lock is "converted" into a
-legacy resource lock. The arbiter will first look for all VGA cards that
-might conflict and disable their IOs and/or Memory access, including VGA
-forwarding on P2P bridges if necessary, so that the requested resources can
-be used. Then, the card is marked as locking these resources and the IO and/or
-Memory access is enabled on the card (including VGA forwarding on parent
-P2P bridges if any). In the case of vga_arb_lock(), the function will block
-if some conflicting card is already locking one of the required resources (or
-any resource on a different bus segment, since P2P bridges don't differentiate
-VGA memory and IO afaik). If the card already owns the resources, the function
-succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
-calls are supported (a per-resource counter is maintained).
-
-
-Set the target device of this client.
-    int  pci_device_vgaarb_set_target   (struct pci_device *dev);
-
-
-For instance, in x86 if two devices on the same bus want to lock different
-resources, both will succeed (lock). If devices are in different buses and
-trying to lock different resources, only the first who tried succeeds.
-    int  pci_device_vgaarb_lock         (void);
-    int  pci_device_vgaarb_trylock      (void);
-
-Unlock resources of device.
-    int  pci_device_vgaarb_unlock       (void);
-
-Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
-Memory, both, or none. All cards default to both, the card driver (fbdev for
-example) should tell the arbiter if it has disabled legacy decoding, so the
-card can be left out of the arbitration process (and can be safe to take
-interrupts at any time.
-    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);
-
-Connects to the arbiter device, allocates the struct
-    int  pci_device_vgaarb_init         (void);
-
-Close the connection
-    void pci_device_vgaarb_fini         (void);
-
-
-I.3 xf86VGAArbiter (X server implementation)
---------------------------------------------
-
-(TODO)
-
-X server basically wraps all the functions that touch VGA registers somehow.
-
-
-II. Credits
-===========
-
-Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
-with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
-Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
-enhancing the kernel code to adapt as a kernel module and also did the
-implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
-Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
-
-
-III. References
-==============
-
-[0] http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
-[1] http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
-[2] http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
-[3] http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index f17cb0431833..1887f199ccb7 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -131,7 +131,24 @@ static struct vga_device *vgadev_find(struct pci_dev *pdev)
 	return NULL;
 }
 
-/* Returns the default VGA device (vgacon's babe) */
+/**
+ * vga_default_device - return the default VGA device, for vgacon
+ *
+ * This can be defined by the platform. The default implementation
+ * is rather dumb and will probably only work properly on single
+ * vga card setups and/or x86 platforms.
+ *
+ * If your VGA default device is not PCI, you'll have to return
+ * NULL here. In this case, I assume it will not conflict with
+ * any PCI card. If this is not true, I'll have to define two archs
+ * hooks for enabling/disabling the VGA default device if that is
+ * possible. This may be a problem with real _ISA_ VGA cards, in
+ * addition to a PCI one. I don't know at this point how to deal
+ * with that card. Can theirs IOs be disabled at all ? If not, then
+ * I suppose it's a matter of having the proper arch hook telling
+ * us about it, so we basically never allow anybody to succeed a
+ * vga_get()...
+ */
 struct pci_dev *vga_default_device(void)
 {
 	return vga_default;
@@ -356,6 +373,40 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
 		wake_up_all(&vga_wait_queue);
 }
 
+/**
+ * vga_get - acquire & locks VGA resources
+ * @pdev: pci device of the VGA card or NULL for the system default
+ * @rsrc: bit mask of resources to acquire and lock
+ * @interruptible: blocking should be interruptible by signals ?
+ *
+ * This function acquires VGA resources for the given card and mark those
+ * resources locked. If the resource requested are "normal" (and not legacy)
+ * resources, the arbiter will first check whether the card is doing legacy
+ * decoding for that type of resource. If yes, the lock is "converted" into a
+ * legacy resource lock.
+ *
+ * The arbiter will first look for all VGA cards that might conflict and disable
+ * their IOs and/or Memory access, including VGA forwarding on P2P bridges if
+ * necessary, so that the requested resources can be used. Then, the card is
+ * marked as locking these resources and the IO and/or Memory accesses are
+ * enabled on the card (including VGA forwarding on parent P2P bridges if any).
+ *
+ * This function will block if some conflicting card is already locking one of
+ * the required resources (or any resource on a different bus segment, since P2P
+ * bridges don't differentiate VGA memory and IO afaik). You can indicate
+ * whether this blocking should be interruptible by a signal (for userland
+ * interface) or not.
+ *
+ * Must not be called at interrupt time or in atomic context.  If the card
+ * already owns the resources, the function succeeds.  Nested calls are
+ * supported (a per-resource counter is maintained)
+ *
+ * On success, release the VGA resource again with vga_put().
+ *
+ * Returns:
+ *
+ * 0 on success, negative error code on failure.
+ */
 int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
 {
 	struct vga_device *vgadev, *conflict;
@@ -408,6 +459,21 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
 }
 EXPORT_SYMBOL(vga_get);
 
+/**
+ * vga_tryget - try to acquire & lock legacy VGA resources
+ * @pdev: pci devivce of VGA card or NULL for system default
+ * @rsrc: bit mask of resources to acquire and lock
+ *
+ * This function performs the same operation as vga_get(), but will return an
+ * error (-EBUSY) instead of blocking if the resources are already locked by
+ * another card. It can be called in any context
+ *
+ * On success, release the VGA resource again with vga_put().
+ *
+ * Returns:
+ *
+ * 0 on success, negative error code on failure.
+ */
 int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
 {
 	struct vga_device *vgadev;
@@ -435,6 +501,16 @@ bail:
 }
 EXPORT_SYMBOL(vga_tryget);
 
+/**
+ * vga_put - release lock on legacy VGA resources
+ * @pdev: pci device of VGA card or NULL for system default
+ * @rsrc: but mask of resource to release
+ *
+ * This fuction releases resources previously locked by vga_get() or
+ * vga_tryget(). The resources aren't disabled right away, so that a subsequence
+ * vga_get() on the same card will succeed immediately. Resources have a
+ * counter, so locks are only released if the counter reaches 0.
+ */
 void vga_put(struct pci_dev *pdev, unsigned int rsrc)
 {
 	struct vga_device *vgadev;
@@ -716,7 +792,37 @@ void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes)
 }
 EXPORT_SYMBOL(vga_set_legacy_decoding);
 
-/* call with NULL to unregister */
+/**
+ * vga_client_register - register or unregister a VGA arbitration client
+ * @pdev: pci device of the VGA client
+ * @cookie: client cookie to be used in callbacks
+ * @irq_set_state: irq state change callback
+ * @set_vga_decode: vga decode change callback
+ *
+ * Clients have two callback mechanisms they can use.
+ *
+ * @irq_set_state callback: If a client can't disable its GPUs VGA
+ * resources, then we need to be able to ask it to turn off its irqs when we
+ * turn off its mem and io decoding.
+ *
+ * @set_vga_decode callback: If a client can disable its GPU VGA resource, it
+ * will get a callback from this to set the encode/decode state.
+ *
+ * Rationale: we cannot disable VGA decode resources unconditionally some single
+ * GPU laptops seem to require ACPI or BIOS access to the VGA registers to
+ * control things like backlights etc.  Hopefully newer multi-GPU laptops do
+ * something saner, and desktops won't have any special ACPI for this. The
+ * driver will get a callback when VGA arbitration is first used by userspace
+ * since some older X servers have issues.
+ *
+ * This function does not check whether a client for @pdev has been registered
+ * already.
+ *
+ * To unregister just call this function with @irq_set_state and @set_vga_decode
+ * both set to NULL for the same @pdev as originally used to register them.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
 int vga_client_register(struct pci_dev *pdev, void *cookie,
 			void (*irq_set_state)(void *cookie, bool state),
 			unsigned int (*set_vga_decode)(void *cookie,
diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
index 8c3b412d84df..ee162e3e879b 100644
--- a/include/linux/vgaarb.h
+++ b/include/linux/vgaarb.h
@@ -73,34 +73,6 @@ static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
 					   unsigned int decodes) { };
 #endif
 
-/**
- *     vga_get         - acquire & locks VGA resources
- *
- *     @pdev: pci device of the VGA card or NULL for the system default
- *     @rsrc: bit mask of resources to acquire and lock
- *     @interruptible: blocking should be interruptible by signals ?
- *
- *     This function acquires VGA resources for the given
- *     card and mark those resources locked. If the resource requested
- *     are "normal" (and not legacy) resources, the arbiter will first check
- *     whether the card is doing legacy decoding for that type of resource. If
- *     yes, the lock is "converted" into a legacy resource lock.
- *     The arbiter will first look for all VGA cards that might conflict
- *     and disable their IOs and/or Memory access, including VGA forwarding
- *     on P2P bridges if necessary, so that the requested resources can
- *     be used. Then, the card is marked as locking these resources and
- *     the IO and/or Memory accesse are enabled on the card (including
- *     VGA forwarding on parent P2P bridges if any).
- *     This function will block if some conflicting card is already locking
- *     one of the required resources (or any resource on a different bus
- *     segment, since P2P bridges don't differenciate VGA memory and IO
- *     afaik). You can indicate whether this blocking should be interruptible
- *     by a signal (for userland interface) or not.
- *     Must not be called at interrupt time or in atomic context.
- *     If the card already owns the resources, the function succeeds.
- *     Nested calls are supported (a per-resource counter is maintained)
- */
-
 #if defined(CONFIG_VGA_ARB)
 extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
 #else
@@ -108,11 +80,14 @@ static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interrupt
 #endif
 
 /**
- *     vga_get_interruptible
+ * vga_get_interruptible
+ * @pdev: pci device of the VGA card or NULL for the system default
+ * @rsrc: bit mask of resources to acquire and lock
  *
- *     Shortcut to vga_get
+ * Shortcut to vga_get with interruptible set to true.
+ *
+ * On success, release the VGA resource again with vga_put().
  */
-
 static inline int vga_get_interruptible(struct pci_dev *pdev,
 					unsigned int rsrc)
 {
@@ -120,47 +95,26 @@ static inline int vga_get_interruptible(struct pci_dev *pdev,
 }
 
 /**
- *     vga_get_uninterruptible
+ * vga_get_uninterruptible - shortcut to vga_get()
+ * @pdev: pci device of the VGA card or NULL for the system default
+ * @rsrc: bit mask of resources to acquire and lock
  *
- *     Shortcut to vga_get
+ * Shortcut to vga_get with interruptible set to false.
+ *
+ * On success, release the VGA resource again with vga_put().
  */
-
 static inline int vga_get_uninterruptible(struct pci_dev *pdev,
 					  unsigned int rsrc)
 {
        return vga_get(pdev, rsrc, 0);
 }
 
-/**
- *     vga_tryget      - try to acquire & lock legacy VGA resources
- *
- *     @pdev: pci devivce of VGA card or NULL for system default
- *     @rsrc: bit mask of resources to acquire and lock
- *
- *     This function performs the same operation as vga_get(), but
- *     will return an error (-EBUSY) instead of blocking if the resources
- *     are already locked by another card. It can be called in any context
- */
-
 #if defined(CONFIG_VGA_ARB)
 extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc);
 #else
 static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; }
 #endif
 
-/**
- *     vga_put         - release lock on legacy VGA resources
- *
- *     @pdev: pci device of VGA card or NULL for system default
- *     @rsrc: but mask of resource to release
- *
- *     This function releases resources previously locked by vga_get()
- *     or vga_tryget(). The resources aren't disabled right away, so
- *     that a subsequence vga_get() on the same card will succeed
- *     immediately. Resources have a counter, so locks are only
- *     released if the counter reaches 0.
- */
-
 #if defined(CONFIG_VGA_ARB)
 extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
 #else
@@ -168,25 +122,6 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
 #endif
 
 
-/**
- *     vga_default_device
- *
- *     This can be defined by the platform. The default implementation
- *     is rather dumb and will probably only work properly on single
- *     vga card setups and/or x86 platforms.
- *
- *     If your VGA default device is not PCI, you'll have to return
- *     NULL here. In this case, I assume it will not conflict with
- *     any PCI card. If this is not true, I'll have to define two archs
- *     hooks for enabling/disabling the VGA default device if that is
- *     possible. This may be a problem with real _ISA_ VGA cards, in
- *     addition to a PCI one. I don't know at this point how to deal
- *     with that card. Can theirs IOs be disabled at all ? If not, then
- *     I suppose it's a matter of having the proper arch hook telling
- *     us about it, so we basically never allow anybody to succeed a
- *     vga_get()...
- */
-
 #ifdef CONFIG_VGA_ARB
 extern struct pci_dev *vga_default_device(void);
 extern void vga_set_default_device(struct pci_dev *pdev);
@@ -195,14 +130,11 @@ static inline struct pci_dev *vga_default_device(void) { return NULL; };
 static inline void vga_set_default_device(struct pci_dev *pdev) { };
 #endif
 
-/**
- *     vga_conflicts
- *
- *     Architectures should define this if they have several
- *     independent PCI domains that can afford concurrent VGA
- *     decoding
+/*
+ * Architectures should define this if they have several
+ * independent PCI domains that can afford concurrent VGA
+ * decoding
  */
-
 #ifndef __ARCH_HAS_VGA_CONFLICT
 static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
 {
@@ -210,34 +142,6 @@ static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
 }
 #endif
 
-/**
- *	vga_client_register
- *
- *	@pdev: pci device of the VGA client
- *	@cookie: client cookie to be used in callbacks
- *	@irq_set_state: irq state change callback
- *	@set_vga_decode: vga decode change callback
- *
- * 	return value: 0 on success, -1 on failure
- * 	Register a client with the VGA arbitration logic
- *
- *	Clients have two callback mechanisms they can use.
- *	irq enable/disable callback -
- *		If a client can't disable its GPUs VGA resources, then we
- *		need to be able to ask it to turn off its irqs when we
- *		turn off its mem and io decoding.
- *	set_vga_decode
- *		If a client can disable its GPU VGA resource, it will
- *		get a callback from this to set the encode/decode state
- *
- * Rationale: we cannot disable VGA decode resources unconditionally
- * some single GPU laptops seem to require ACPI or BIOS access to the
- * VGA registers to control things like backlights etc.
- * Hopefully newer multi-GPU laptops do something saner, and desktops
- * won't have any special ACPI for this.
- * They driver will get a callback when VGA arbitration is first used
- * by userspace since we some older X servers have issues.
- */
 #if defined(CONFIG_VGA_ARB)
 int vga_client_register(struct pci_dev *pdev, void *cookie,
 			void (*irq_set_state)(void *cookie, bool state),
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (18 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc Daniel Vetter
@ 2016-08-12 20:48 ` Daniel Vetter
  2016-08-15 20:14   ` Sean Paul
  2016-08-16 13:42 ` [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Sean Paul
  20 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-12 20:48 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter, Daniel Vetter

Ville ocd'ed the parameter name, but forgot to update the docs!

Fixes: df86af9133b4 ("drm/plane-helper: Add drm_plane_helper_check_state()")
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
---
 drivers/gpu/drm/drm_plane_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 50b9c1bfc6f6..7899fc1dcdb0 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_state);
  * @crtc: owning CRTC of owning plane
  * @fb: framebuffer to flip onto plane
  * @src: source coordinates in 16.16 fixed point
- * @dest: integer destination coordinates
+ * @dst: integer destination coordinates
  * @clip: integer clipping coordinates
  * @rotation: plane rotation
  * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
-- 
2.8.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev
  2016-08-12 20:48 ` [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev Daniel Vetter
@ 2016-08-15  9:07   ` Lucas Stach
  0 siblings, 0 replies; 36+ messages in thread
From: Lucas Stach @ 2016-08-15  9:07 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Russell King, DRI Development, Daniel Vetter

Am Freitag, den 12.08.2016, 22:48 +0200 schrieb Daniel Vetter:
> It's deprecated and only should be used by drivers which still use
> drm_platform_init, not by anyone else.
> 
> And indeed it's entirely unused and can be nuked.
> 
> Cc: Lucas Stach <l.stach@pengutronix.de>
> Cc: Russell King <rmk+kernel@arm.linux.org.uk>
> Cc: Christian Gmeiner <christian.gmeiner@gmail.com>
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Yeah, I've had this on my list of cleanups to do, so:
Acked-by: Lucas Stach <l.stach@pengutronix.de>

I suppose you are taking this through the misc tree, if not please ping
me.
> ---
>  drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> index ffd1b32caa8d..0c00947d15f2 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
> @@ -533,8 +533,6 @@ static int etnaviv_bind(struct device *dev)
>  	if (!drm)
>  		return -ENOMEM;
>  
> -	drm->platformdev = to_platform_device(dev);
> -
>  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>  	if (!priv) {
>  		dev_err(dev, "failed to allocate private data\n");


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH] drm: Extract drm_framebuffer.[hc]
  2016-08-12 20:48 ` [PATCH 11/21] drm: Extract drm_framebuffer.[hc] Daniel Vetter
@ 2016-08-15 14:07   ` Daniel Vetter
  2016-08-15 20:15     ` Sean Paul
  0 siblings, 1 reply; 36+ messages in thread
From: Daniel Vetter @ 2016-08-15 14:07 UTC (permalink / raw)
  To: DRI Development; +Cc: Daniel Vetter

Also start with drm_modeset.h with the core bits, since we need
to untangle this mess somehow. That allows us to move the drm_modes.h
include to the right spot, except for the temporary connector status
enum. That will get fixed as soon as drm_connector.h exists.

v2: Rebase.

v3: Move drm_crtc_force_disable_all back again, that wasn't meant to
be moved (Sean).

v4: Rebase.

Cc: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 Documentation/gpu/drm-kms.rst       |   9 +
 drivers/gpu/drm/Makefile            |   3 +-
 drivers/gpu/drm/drm_crtc.c          | 807 +-----------------------------------
 drivers/gpu/drm/drm_crtc_internal.h |  40 +-
 drivers/gpu/drm/drm_framebuffer.c   | 799 +++++++++++++++++++++++++++++++++++
 include/drm/drm_crtc.h              | 162 +-------
 include/drm/drm_framebuffer.h       | 170 ++++++++
 include/drm/drm_modes.h             |   2 +
 include/drm/drm_modeset.h           |  50 +++
 9 files changed, 1078 insertions(+), 964 deletions(-)
 create mode 100644 drivers/gpu/drm/drm_framebuffer.c
 create mode 100644 include/drm/drm_framebuffer.h
 create mode 100644 include/drm/drm_modeset.h

diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
index 3ae4c12aca08..8264a88a8695 100644
--- a/Documentation/gpu/drm-kms.rst
+++ b/Documentation/gpu/drm-kms.rst
@@ -64,6 +64,15 @@ fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
 drivers can manually clean up a framebuffer at module unload time with
 :c:func:`drm_framebuffer_unregister_private()`.
 
+Frame Buffer Functions Reference
+--------------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
+   :export:
+
+.. kernel-doc:: include/drm/drm_framebuffer.h
+   :internal:
+
 DRM Format Handling
 ===================
 
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index a5824d926dc9..c71ec42ce511 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -12,7 +12,8 @@ drm-y       :=	drm_auth.o drm_bufs.o drm_cache.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.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_modeset_lock.o drm_atomic.o drm_bridge.o \
+		drm_framebuffer.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_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 4499126321e0..b38dd10841e6 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -40,15 +40,11 @@
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_auth.h>
+#include <drm/drm_framebuffer.h>
 
 #include "drm_crtc_internal.h"
 #include "drm_internal.h"
 
-static struct drm_framebuffer *
-internal_framebuffer_create(struct drm_device *dev,
-			    const struct drm_mode_fb_cmd2 *r,
-			    struct drm_file *file_priv);
-
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list)				\
 	const char *fnname(int val)				\
@@ -238,11 +234,11 @@ 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.
  */
-static int drm_mode_object_get_reg(struct drm_device *dev,
-				   struct drm_mode_object *obj,
-				   uint32_t obj_type,
-				   bool register_obj,
-				   void (*obj_free_cb)(struct kref *kref))
+int drm_mode_object_get_reg(struct drm_device *dev,
+			    struct drm_mode_object *obj,
+			    uint32_t obj_type,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref))
 {
 	int ret;
 
@@ -285,8 +281,8 @@ int drm_mode_object_get(struct drm_device *dev,
 	return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
 }
 
-static void drm_mode_object_register(struct drm_device *dev,
-				     struct drm_mode_object *obj)
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj)
 {
 	mutex_lock(&dev->mode_config.idr_mutex);
 	idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
@@ -315,8 +311,8 @@ void drm_mode_object_unregister(struct drm_device *dev,
 	mutex_unlock(&dev->mode_config.idr_mutex);
 }
 
-static struct drm_mode_object *_object_find(struct drm_device *dev,
-		uint32_t id, uint32_t type)
+struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+					       uint32_t id, uint32_t type)
 {
 	struct drm_mode_object *obj = NULL;
 
@@ -351,7 +347,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
 {
 	struct drm_mode_object *obj = NULL;
 
-	obj = _object_find(dev, id, type);
+	obj = __drm_mode_object_find(dev, id, type);
 	return obj;
 }
 EXPORT_SYMBOL(drm_mode_object_find);
@@ -435,205 +431,6 @@ out:
 }
 EXPORT_SYMBOL(drm_crtc_force_disable_all);
 
-static void drm_framebuffer_free(struct kref *kref)
-{
-	struct drm_framebuffer *fb =
-			container_of(kref, struct drm_framebuffer, base.refcount);
-	struct drm_device *dev = fb->dev;
-
-	/*
-	 * The lookup idr holds a weak reference, which has not necessarily been
-	 * removed at this point. Check for that.
-	 */
-	drm_mode_object_unregister(dev, &fb->base);
-
-	fb->funcs->destroy(fb);
-}
-
-/**
- * drm_framebuffer_init - initialize a framebuffer
- * @dev: DRM device
- * @fb: framebuffer to be initialized
- * @funcs: ... with these functions
- *
- * Allocates an ID for the framebuffer's parent mode object, sets its mode
- * functions & device file and adds it to the master fd list.
- *
- * IMPORTANT:
- * This functions publishes the fb and makes it available for concurrent access
- * by other users. Which means by this point the fb _must_ be fully set up -
- * since all the fb attributes are invariant over its lifetime, no further
- * locking but only correct reference counting is required.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
-			 const struct drm_framebuffer_funcs *funcs)
-{
-	int ret;
-
-	INIT_LIST_HEAD(&fb->filp_head);
-	fb->dev = dev;
-	fb->funcs = funcs;
-
-	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
-				      false, drm_framebuffer_free);
-	if (ret)
-		goto out;
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	dev->mode_config.num_fb++;
-	list_add(&fb->head, &dev->mode_config.fb_list);
-	mutex_unlock(&dev->mode_config.fb_lock);
-
-	drm_mode_object_register(dev, &fb->base);
-out:
-	return ret;
-}
-EXPORT_SYMBOL(drm_framebuffer_init);
-
-/**
- * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
- * @dev: drm device
- * @id: id of the fb object
- *
- * If successful, this grabs an additional reference to the framebuffer -
- * callers need to make sure to eventually unreference the returned framebuffer
- * again, using @drm_framebuffer_unreference.
- */
-struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
-					       uint32_t id)
-{
-	struct drm_mode_object *obj;
-	struct drm_framebuffer *fb = NULL;
-
-	obj = _object_find(dev, id, DRM_MODE_OBJECT_FB);
-	if (obj)
-		fb = obj_to_fb(obj);
-	return fb;
-}
-EXPORT_SYMBOL(drm_framebuffer_lookup);
-
-/**
- * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
- * @fb: fb to unregister
- *
- * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
- * those used for fbdev. Note that the caller must hold a reference of it's own,
- * i.e. the object may not be destroyed through this call (since it'll lead to a
- * locking inversion).
- */
-void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev;
-
-	if (!fb)
-		return;
-
-	dev = fb->dev;
-
-	/* Mark fb as reaped and drop idr ref. */
-	drm_mode_object_unregister(dev, &fb->base);
-}
-EXPORT_SYMBOL(drm_framebuffer_unregister_private);
-
-/**
- * drm_framebuffer_cleanup - remove a framebuffer object
- * @fb: framebuffer to remove
- *
- * Cleanup framebuffer. This function is intended to be used from the drivers
- * ->destroy callback. It can also be used to clean up driver private
- * framebuffers embedded into a larger structure.
- *
- * Note that this function does not remove the fb from active usuage - if it is
- * still used anywhere, hilarity can ensue since userspace could call getfb on
- * the id and get back -EINVAL. Obviously no concern at driver unload time.
- *
- * Also, the framebuffer will not be removed from the lookup idr - for
- * user-created framebuffers this will happen in in the rmfb ioctl. For
- * driver-private objects (e.g. for fbdev) drivers need to explicitly call
- * drm_framebuffer_unregister_private.
- */
-void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev = fb->dev;
-
-	mutex_lock(&dev->mode_config.fb_lock);
-	list_del(&fb->head);
-	dev->mode_config.num_fb--;
-	mutex_unlock(&dev->mode_config.fb_lock);
-}
-EXPORT_SYMBOL(drm_framebuffer_cleanup);
-
-/**
- * drm_framebuffer_remove - remove and unreference a framebuffer object
- * @fb: framebuffer to remove
- *
- * Scans all the CRTCs and planes in @dev's mode_config.  If they're
- * using @fb, removes it, setting it to NULL. Then drops the reference to the
- * passed-in framebuffer. Might take the modeset locks.
- *
- * Note that this function optimizes the cleanup away if the caller holds the
- * last reference to the framebuffer. It is also guaranteed to not take the
- * modeset locks in this case.
- */
-void drm_framebuffer_remove(struct drm_framebuffer *fb)
-{
-	struct drm_device *dev;
-	struct drm_crtc *crtc;
-	struct drm_plane *plane;
-
-	if (!fb)
-		return;
-
-	dev = fb->dev;
-
-	WARN_ON(!list_empty(&fb->filp_head));
-
-	/*
-	 * drm ABI mandates that we remove any deleted framebuffers from active
-	 * useage. But since most sane clients only remove framebuffers they no
-	 * longer need, try to optimize this away.
-	 *
-	 * Since we're holding a reference ourselves, observing a refcount of 1
-	 * means that we're the last holder and can skip it. Also, the refcount
-	 * can never increase from 1 again, so we don't need any barriers or
-	 * locks.
-	 *
-	 * Note that userspace could try to race with use and instate a new
-	 * usage _after_ we've cleared all current ones. End result will be an
-	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
-	 * in this manner.
-	 */
-	if (drm_framebuffer_read_refcount(fb) > 1) {
-		if (dev->mode_config.funcs->atomic_commit) {
-			drm_atomic_remove_fb(fb);
-			goto out;
-		}
-
-		drm_modeset_lock_all(dev);
-		/* remove from any CRTC */
-		drm_for_each_crtc(crtc, dev) {
-			if (crtc->primary->fb == fb) {
-				/* should turn off the crtc */
-				if (drm_crtc_force_disable(crtc))
-					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
-			}
-		}
-
-		drm_for_each_plane(plane, dev) {
-			if (plane->fb == fb)
-				drm_plane_force_disable(plane);
-		}
-		drm_modeset_unlock_all(dev);
-	}
-
-out:
-	drm_framebuffer_unreference(fb);
-}
-EXPORT_SYMBOL(drm_framebuffer_remove);
-
 DEFINE_WW_CLASS(crtc_ww_class);
 
 static unsigned int drm_num_crtcs(struct drm_device *dev)
@@ -3012,7 +2809,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
 	 */
 	if (req->flags & DRM_MODE_CURSOR_BO) {
 		if (req->handle) {
-			fb = internal_framebuffer_create(dev, &fbreq, file_priv);
+			fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
 			if (IS_ERR(fb)) {
 				DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
 				return PTR_ERR(fb);
@@ -3210,581 +3007,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
 }
 EXPORT_SYMBOL(drm_mode_legacy_fb_format);
 
-/**
- * drm_mode_addfb - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request. This is the
- * original addfb ioctl which only supported RGB formats.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_addfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd *or = data;
-	struct drm_mode_fb_cmd2 r = {};
-	int ret;
-
-	/* convert to new format and call new ioctl */
-	r.fb_id = or->fb_id;
-	r.width = or->width;
-	r.height = or->height;
-	r.pitches[0] = or->pitch;
-	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
-	r.handles[0] = or->handle;
-
-	ret = drm_mode_addfb2(dev, &r, file_priv);
-	if (ret)
-		return ret;
-
-	or->fb_id = r.fb_id;
-
-	return 0;
-}
-
-static int format_check(const struct drm_mode_fb_cmd2 *r)
-{
-	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
-	const char *format_name;
-
-	switch (format) {
-	case DRM_FORMAT_C8:
-	case DRM_FORMAT_RGB332:
-	case DRM_FORMAT_BGR233:
-	case DRM_FORMAT_XRGB4444:
-	case DRM_FORMAT_XBGR4444:
-	case DRM_FORMAT_RGBX4444:
-	case DRM_FORMAT_BGRX4444:
-	case DRM_FORMAT_ARGB4444:
-	case DRM_FORMAT_ABGR4444:
-	case DRM_FORMAT_RGBA4444:
-	case DRM_FORMAT_BGRA4444:
-	case DRM_FORMAT_XRGB1555:
-	case DRM_FORMAT_XBGR1555:
-	case DRM_FORMAT_RGBX5551:
-	case DRM_FORMAT_BGRX5551:
-	case DRM_FORMAT_ARGB1555:
-	case DRM_FORMAT_ABGR1555:
-	case DRM_FORMAT_RGBA5551:
-	case DRM_FORMAT_BGRA5551:
-	case DRM_FORMAT_RGB565:
-	case DRM_FORMAT_BGR565:
-	case DRM_FORMAT_RGB888:
-	case DRM_FORMAT_BGR888:
-	case DRM_FORMAT_XRGB8888:
-	case DRM_FORMAT_XBGR8888:
-	case DRM_FORMAT_RGBX8888:
-	case DRM_FORMAT_BGRX8888:
-	case DRM_FORMAT_ARGB8888:
-	case DRM_FORMAT_ABGR8888:
-	case DRM_FORMAT_RGBA8888:
-	case DRM_FORMAT_BGRA8888:
-	case DRM_FORMAT_XRGB2101010:
-	case DRM_FORMAT_XBGR2101010:
-	case DRM_FORMAT_RGBX1010102:
-	case DRM_FORMAT_BGRX1010102:
-	case DRM_FORMAT_ARGB2101010:
-	case DRM_FORMAT_ABGR2101010:
-	case DRM_FORMAT_RGBA1010102:
-	case DRM_FORMAT_BGRA1010102:
-	case DRM_FORMAT_YUYV:
-	case DRM_FORMAT_YVYU:
-	case DRM_FORMAT_UYVY:
-	case DRM_FORMAT_VYUY:
-	case DRM_FORMAT_AYUV:
-	case DRM_FORMAT_NV12:
-	case DRM_FORMAT_NV21:
-	case DRM_FORMAT_NV16:
-	case DRM_FORMAT_NV61:
-	case DRM_FORMAT_NV24:
-	case DRM_FORMAT_NV42:
-	case DRM_FORMAT_YUV410:
-	case DRM_FORMAT_YVU410:
-	case DRM_FORMAT_YUV411:
-	case DRM_FORMAT_YVU411:
-	case DRM_FORMAT_YUV420:
-	case DRM_FORMAT_YVU420:
-	case DRM_FORMAT_YUV422:
-	case DRM_FORMAT_YVU422:
-	case DRM_FORMAT_YUV444:
-	case DRM_FORMAT_YVU444:
-		return 0;
-	default:
-		format_name = drm_get_format_name(r->pixel_format);
-		DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
-		kfree(format_name);
-		return -EINVAL;
-	}
-}
-
-static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
-{
-	int ret, hsub, vsub, num_planes, i;
-
-	ret = format_check(r);
-	if (ret) {
-		const char *format_name = drm_get_format_name(r->pixel_format);
-		DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name);
-		kfree(format_name);
-		return ret;
-	}
-
-	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
-	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
-	num_planes = drm_format_num_planes(r->pixel_format);
-
-	if (r->width == 0 || r->width % hsub) {
-		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
-		return -EINVAL;
-	}
-
-	if (r->height == 0 || r->height % vsub) {
-		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < num_planes; i++) {
-		unsigned int width = r->width / (i != 0 ? hsub : 1);
-		unsigned int height = r->height / (i != 0 ? vsub : 1);
-		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
-
-		if (!r->handles[i]) {
-			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if ((uint64_t) width * cpp > UINT_MAX)
-			return -ERANGE;
-
-		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
-			return -ERANGE;
-
-		if (r->pitches[i] < width * cpp) {
-			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
-			return -EINVAL;
-		}
-
-		if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
-			DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
-				      r->modifier[i], i);
-			return -EINVAL;
-		}
-
-		/* modifier specific checks: */
-		switch (r->modifier[i]) {
-		case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
-			/* NOTE: the pitch restriction may be lifted later if it turns
-			 * out that no hw has this restriction:
-			 */
-			if (r->pixel_format != DRM_FORMAT_NV12 ||
-					width % 128 || height % 32 ||
-					r->pitches[i] % 128) {
-				DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
-				return -EINVAL;
-			}
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	for (i = num_planes; i < 4; i++) {
-		if (r->modifier[i]) {
-			DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
-		if (!(r->flags & DRM_MODE_FB_MODIFIERS))
-			continue;
-
-		if (r->handles[i]) {
-			DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if (r->pitches[i]) {
-			DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
-			return -EINVAL;
-		}
-
-		if (r->offsets[i]) {
-			DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-static struct drm_framebuffer *
-internal_framebuffer_create(struct drm_device *dev,
-			    const struct drm_mode_fb_cmd2 *r,
-			    struct drm_file *file_priv)
-{
-	struct drm_mode_config *config = &dev->mode_config;
-	struct drm_framebuffer *fb;
-	int ret;
-
-	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
-		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if ((config->min_width > r->width) || (r->width > config->max_width)) {
-		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
-			  r->width, config->min_width, config->max_width);
-		return ERR_PTR(-EINVAL);
-	}
-	if ((config->min_height > r->height) || (r->height > config->max_height)) {
-		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
-			  r->height, config->min_height, config->max_height);
-		return ERR_PTR(-EINVAL);
-	}
-
-	if (r->flags & DRM_MODE_FB_MODIFIERS &&
-	    !dev->mode_config.allow_fb_modifiers) {
-		DRM_DEBUG_KMS("driver does not support fb modifiers\n");
-		return ERR_PTR(-EINVAL);
-	}
-
-	ret = framebuffer_check(r);
-	if (ret)
-		return ERR_PTR(ret);
-
-	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
-	if (IS_ERR(fb)) {
-		DRM_DEBUG_KMS("could not create framebuffer\n");
-		return fb;
-	}
-
-	return fb;
-}
-
-/**
- * drm_mode_addfb2 - add an FB to the graphics configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Add a new FB to the specified CRTC, given a user request with format. This is
- * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
- * and uses fourcc codes as pixel format specifiers.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_addfb2(struct drm_device *dev,
-		    void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd2 *r = data;
-	struct drm_framebuffer *fb;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = internal_framebuffer_create(dev, r, file_priv);
-	if (IS_ERR(fb))
-		return PTR_ERR(fb);
-
-	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
-	r->fb_id = fb->base.id;
-
-	/* Transfer ownership to the filp for reaping on close */
-	mutex_lock(&file_priv->fbs_lock);
-	list_add(&fb->filp_head, &file_priv->fbs);
-	mutex_unlock(&file_priv->fbs_lock);
-
-	return 0;
-}
-
-struct drm_mode_rmfb_work {
-	struct work_struct work;
-	struct list_head fbs;
-};
-
-static void drm_mode_rmfb_work_fn(struct work_struct *w)
-{
-	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
-
-	while (!list_empty(&arg->fbs)) {
-		struct drm_framebuffer *fb =
-			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
-
-		list_del_init(&fb->filp_head);
-		drm_framebuffer_remove(fb);
-	}
-}
-
-/**
- * drm_mode_rmfb - remove an FB from the configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Remove the FB specified by the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_rmfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_framebuffer *fb = NULL;
-	struct drm_framebuffer *fbl = NULL;
-	uint32_t *id = data;
-	int found = 0;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, *id);
-	if (!fb)
-		return -ENOENT;
-
-	mutex_lock(&file_priv->fbs_lock);
-	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
-		if (fb == fbl)
-			found = 1;
-	if (!found) {
-		mutex_unlock(&file_priv->fbs_lock);
-		goto fail_unref;
-	}
-
-	list_del_init(&fb->filp_head);
-	mutex_unlock(&file_priv->fbs_lock);
-
-	/* drop the reference we picked up in framebuffer lookup */
-	drm_framebuffer_unreference(fb);
-
-	/*
-	 * we now own the reference that was stored in the fbs list
-	 *
-	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
-	 * so run this in a separate stack as there's no way to correctly
-	 * handle this after the fb is already removed from the lookup table.
-	 */
-	if (drm_framebuffer_read_refcount(fb) > 1) {
-		struct drm_mode_rmfb_work arg;
-
-		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-		INIT_LIST_HEAD(&arg.fbs);
-		list_add_tail(&fb->filp_head, &arg.fbs);
-
-		schedule_work(&arg.work);
-		flush_work(&arg.work);
-		destroy_work_on_stack(&arg.work);
-	} else
-		drm_framebuffer_unreference(fb);
-
-	return 0;
-
-fail_unref:
-	drm_framebuffer_unreference(fb);
-	return -ENOENT;
-}
-
-/**
- * drm_mode_getfb - get FB info
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Lookup the FB given its ID and return info about it.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv)
-{
-	struct drm_mode_fb_cmd *r = data;
-	struct drm_framebuffer *fb;
-	int ret;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, r->fb_id);
-	if (!fb)
-		return -ENOENT;
-
-	r->height = fb->height;
-	r->width = fb->width;
-	r->depth = fb->depth;
-	r->bpp = fb->bits_per_pixel;
-	r->pitch = fb->pitches[0];
-	if (fb->funcs->create_handle) {
-		if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
-		    drm_is_control_client(file_priv)) {
-			ret = fb->funcs->create_handle(fb, file_priv,
-						       &r->handle);
-		} else {
-			/* GET_FB() is an unprivileged ioctl so we must not
-			 * return a buffer-handle to non-master processes! For
-			 * backwards-compatibility reasons, we cannot make
-			 * GET_FB() privileged, so just return an invalid handle
-			 * for non-masters. */
-			r->handle = 0;
-			ret = 0;
-		}
-	} else {
-		ret = -ENODEV;
-	}
-
-	drm_framebuffer_unreference(fb);
-
-	return ret;
-}
-
-/**
- * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Lookup the FB and flush out the damaged area supplied by userspace as a clip
- * rectangle list. Generic userspace which does frontbuffer rendering must call
- * this ioctl to flush out the changes on manual-update display outputs, e.g.
- * usb display-link, mipi manual update panels or edp panel self refresh modes.
- *
- * Modesetting drivers which always update the frontbuffer do not need to
- * implement the corresponding ->dirty framebuffer callback.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv)
-{
-	struct drm_clip_rect __user *clips_ptr;
-	struct drm_clip_rect *clips = NULL;
-	struct drm_mode_fb_dirty_cmd *r = data;
-	struct drm_framebuffer *fb;
-	unsigned flags;
-	int num_clips;
-	int ret;
-
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -EINVAL;
-
-	fb = drm_framebuffer_lookup(dev, r->fb_id);
-	if (!fb)
-		return -ENOENT;
-
-	num_clips = r->num_clips;
-	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
-
-	if (!num_clips != !clips_ptr) {
-		ret = -EINVAL;
-		goto out_err1;
-	}
-
-	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
-
-	/* If userspace annotates copy, clips must come in pairs */
-	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
-		ret = -EINVAL;
-		goto out_err1;
-	}
-
-	if (num_clips && clips_ptr) {
-		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
-			ret = -EINVAL;
-			goto out_err1;
-		}
-		clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
-		if (!clips) {
-			ret = -ENOMEM;
-			goto out_err1;
-		}
-
-		ret = copy_from_user(clips, clips_ptr,
-				     num_clips * sizeof(*clips));
-		if (ret) {
-			ret = -EFAULT;
-			goto out_err2;
-		}
-	}
-
-	if (fb->funcs->dirty) {
-		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
-				       clips, num_clips);
-	} else {
-		ret = -ENOSYS;
-	}
-
-out_err2:
-	kfree(clips);
-out_err1:
-	drm_framebuffer_unreference(fb);
-
-	return ret;
-}
-
-/**
- * drm_fb_release - remove and free the FBs on this file
- * @priv: drm file for the ioctl
- *
- * Destroy all the FBs associated with @filp.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-void drm_fb_release(struct drm_file *priv)
-{
-	struct drm_framebuffer *fb, *tfb;
-	struct drm_mode_rmfb_work arg;
-
-	INIT_LIST_HEAD(&arg.fbs);
-
-	/*
-	 * When the file gets released that means no one else can access the fb
-	 * list any more, so no need to grab fpriv->fbs_lock. And we need to
-	 * avoid upsetting lockdep since the universal cursor code adds a
-	 * framebuffer while holding mutex locks.
-	 *
-	 * Note that a real deadlock between fpriv->fbs_lock and the modeset
-	 * locks is impossible here since no one else but this function can get
-	 * at it any more.
-	 */
-	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
-		if (drm_framebuffer_read_refcount(fb) > 1) {
-			list_move_tail(&fb->filp_head, &arg.fbs);
-		} else {
-			list_del_init(&fb->filp_head);
-
-			/* This drops the fpriv->fbs reference. */
-			drm_framebuffer_unreference(fb);
-		}
-	}
-
-	if (!list_empty(&arg.fbs)) {
-		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
-
-		schedule_work(&arg.work);
-		flush_work(&arg.work);
-		destroy_work_on_stack(&arg.work);
-	}
-}
-
 static bool drm_property_type_valid(struct drm_property *property)
 {
 	if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
@@ -4497,7 +3719,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
 	struct drm_mode_object *obj;
 	struct drm_property_blob *blob = NULL;
 
-	obj = _object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
 	if (obj)
 		blob = obj_to_blob(obj);
 	return blob;
@@ -4893,7 +4115,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
 		if (value == 0)
 			return true;
 
-		*ref = _object_find(property->dev, value, property->values[0]);
+		*ref = __drm_mode_object_find(property->dev, value,
+					      property->values[0]);
 		return *ref != NULL;
 	}
 
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 3ea72e1780b1..5f1e9ff71ae4 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -35,8 +35,17 @@
 /* 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,
+			    bool register_obj,
+			    void (*obj_free_cb)(struct kref *kref));
+void drm_mode_object_register(struct drm_device *dev,
+			      struct drm_mode_object *obj);
 int drm_mode_object_get(struct drm_device *dev,
 			struct drm_mode_object *obj, uint32_t obj_type);
+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);
 bool drm_property_change_valid_get(struct drm_property *property,
@@ -64,18 +73,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
 int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 				void *data, struct drm_file *file_priv);
 
-/* framebuffer IOCTLs */
-extern int drm_mode_addfb(struct drm_device *dev,
-			  void *data, struct drm_file *file_priv);
-extern int drm_mode_addfb2(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv);
-int drm_mode_rmfb(struct drm_device *dev,
-			 void *data, struct drm_file *file_priv);
-int drm_mode_getfb(struct drm_device *dev,
-		   void *data, struct drm_file *file_priv);
-int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
-			   void *data, struct drm_file *file_priv);
-
 /* IOCTLs */
 int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 				      struct drm_file *file_priv);
@@ -120,6 +117,25 @@ 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_framebuffer.c */
+struct drm_framebuffer *
+drm_internal_framebuffer_create(struct drm_device *dev,
+				const struct drm_mode_fb_cmd2 *r,
+				struct drm_file *file_priv);
+void drm_framebuffer_free(struct kref *kref);
+
+/* IOCTL */
+int drm_mode_addfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv);
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv);
+int drm_mode_rmfb(struct drm_device *dev,
+		  void *data, struct drm_file *file_priv);
+int drm_mode_getfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv);
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv);
+
 /* drm_atomic.c */
 int drm_atomic_get_property(struct drm_mode_object *obj,
 			    struct drm_property *property, uint64_t *val);
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
new file mode 100644
index 000000000000..19478a25ac20
--- /dev/null
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -0,0 +1,799 @@
+/*
+ * 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 <linux/export.h>
+#include <drm/drmP.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_framebuffer.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * drm_mode_addfb - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request. This is the
+ * original addfb ioctl which only supported RGB formats.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_addfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd *or = data;
+	struct drm_mode_fb_cmd2 r = {};
+	int ret;
+
+	/* convert to new format and call new ioctl */
+	r.fb_id = or->fb_id;
+	r.width = or->width;
+	r.height = or->height;
+	r.pitches[0] = or->pitch;
+	r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
+	r.handles[0] = or->handle;
+
+	ret = drm_mode_addfb2(dev, &r, file_priv);
+	if (ret)
+		return ret;
+
+	or->fb_id = r.fb_id;
+
+	return 0;
+}
+
+static int format_check(const struct drm_mode_fb_cmd2 *r)
+{
+	uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
+
+	switch (format) {
+	case DRM_FORMAT_C8:
+	case DRM_FORMAT_RGB332:
+	case DRM_FORMAT_BGR233:
+	case DRM_FORMAT_XRGB4444:
+	case DRM_FORMAT_XBGR4444:
+	case DRM_FORMAT_RGBX4444:
+	case DRM_FORMAT_BGRX4444:
+	case DRM_FORMAT_ARGB4444:
+	case DRM_FORMAT_ABGR4444:
+	case DRM_FORMAT_RGBA4444:
+	case DRM_FORMAT_BGRA4444:
+	case DRM_FORMAT_XRGB1555:
+	case DRM_FORMAT_XBGR1555:
+	case DRM_FORMAT_RGBX5551:
+	case DRM_FORMAT_BGRX5551:
+	case DRM_FORMAT_ARGB1555:
+	case DRM_FORMAT_ABGR1555:
+	case DRM_FORMAT_RGBA5551:
+	case DRM_FORMAT_BGRA5551:
+	case DRM_FORMAT_RGB565:
+	case DRM_FORMAT_BGR565:
+	case DRM_FORMAT_RGB888:
+	case DRM_FORMAT_BGR888:
+	case DRM_FORMAT_XRGB8888:
+	case DRM_FORMAT_XBGR8888:
+	case DRM_FORMAT_RGBX8888:
+	case DRM_FORMAT_BGRX8888:
+	case DRM_FORMAT_ARGB8888:
+	case DRM_FORMAT_ABGR8888:
+	case DRM_FORMAT_RGBA8888:
+	case DRM_FORMAT_BGRA8888:
+	case DRM_FORMAT_XRGB2101010:
+	case DRM_FORMAT_XBGR2101010:
+	case DRM_FORMAT_RGBX1010102:
+	case DRM_FORMAT_BGRX1010102:
+	case DRM_FORMAT_ARGB2101010:
+	case DRM_FORMAT_ABGR2101010:
+	case DRM_FORMAT_RGBA1010102:
+	case DRM_FORMAT_BGRA1010102:
+	case DRM_FORMAT_YUYV:
+	case DRM_FORMAT_YVYU:
+	case DRM_FORMAT_UYVY:
+	case DRM_FORMAT_VYUY:
+	case DRM_FORMAT_AYUV:
+	case DRM_FORMAT_NV12:
+	case DRM_FORMAT_NV21:
+	case DRM_FORMAT_NV16:
+	case DRM_FORMAT_NV61:
+	case DRM_FORMAT_NV24:
+	case DRM_FORMAT_NV42:
+	case DRM_FORMAT_YUV410:
+	case DRM_FORMAT_YVU410:
+	case DRM_FORMAT_YUV411:
+	case DRM_FORMAT_YVU411:
+	case DRM_FORMAT_YUV420:
+	case DRM_FORMAT_YVU420:
+	case DRM_FORMAT_YUV422:
+	case DRM_FORMAT_YVU422:
+	case DRM_FORMAT_YUV444:
+	case DRM_FORMAT_YVU444:
+		return 0;
+	default:
+		DRM_DEBUG_KMS("invalid pixel format %s\n",
+			      drm_get_format_name(r->pixel_format));
+		return -EINVAL;
+	}
+}
+
+static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
+{
+	int ret, hsub, vsub, num_planes, i;
+
+	ret = format_check(r);
+	if (ret) {
+		DRM_DEBUG_KMS("bad framebuffer format %s\n",
+			      drm_get_format_name(r->pixel_format));
+		return ret;
+	}
+
+	hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
+	vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
+	num_planes = drm_format_num_planes(r->pixel_format);
+
+	if (r->width == 0 || r->width % hsub) {
+		DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
+		return -EINVAL;
+	}
+
+	if (r->height == 0 || r->height % vsub) {
+		DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_planes; i++) {
+		unsigned int width = r->width / (i != 0 ? hsub : 1);
+		unsigned int height = r->height / (i != 0 ? vsub : 1);
+		unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
+
+		if (!r->handles[i]) {
+			DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if ((uint64_t) width * cpp > UINT_MAX)
+			return -ERANGE;
+
+		if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
+			return -ERANGE;
+
+		if (r->pitches[i] < width * cpp) {
+			DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
+			return -EINVAL;
+		}
+
+		if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
+			DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
+				      r->modifier[i], i);
+			return -EINVAL;
+		}
+
+		/* modifier specific checks: */
+		switch (r->modifier[i]) {
+		case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
+			/* NOTE: the pitch restriction may be lifted later if it turns
+			 * out that no hw has this restriction:
+			 */
+			if (r->pixel_format != DRM_FORMAT_NV12 ||
+					width % 128 || height % 32 ||
+					r->pitches[i] % 128) {
+				DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
+				return -EINVAL;
+			}
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	for (i = num_planes; i < 4; i++) {
+		if (r->modifier[i]) {
+			DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		/* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
+		if (!(r->flags & DRM_MODE_FB_MODIFIERS))
+			continue;
+
+		if (r->handles[i]) {
+			DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if (r->pitches[i]) {
+			DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
+			return -EINVAL;
+		}
+
+		if (r->offsets[i]) {
+			DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+struct drm_framebuffer *
+drm_internal_framebuffer_create(struct drm_device *dev,
+				const struct drm_mode_fb_cmd2 *r,
+				struct drm_file *file_priv)
+{
+	struct drm_mode_config *config = &dev->mode_config;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
+		DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if ((config->min_width > r->width) || (r->width > config->max_width)) {
+		DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
+			  r->width, config->min_width, config->max_width);
+		return ERR_PTR(-EINVAL);
+	}
+	if ((config->min_height > r->height) || (r->height > config->max_height)) {
+		DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
+			  r->height, config->min_height, config->max_height);
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (r->flags & DRM_MODE_FB_MODIFIERS &&
+	    !dev->mode_config.allow_fb_modifiers) {
+		DRM_DEBUG_KMS("driver does not support fb modifiers\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	ret = framebuffer_check(r);
+	if (ret)
+		return ERR_PTR(ret);
+
+	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
+	if (IS_ERR(fb)) {
+		DRM_DEBUG_KMS("could not create framebuffer\n");
+		return fb;
+	}
+
+	return fb;
+}
+
+/**
+ * drm_mode_addfb2 - add an FB to the graphics configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Add a new FB to the specified CRTC, given a user request with format. This is
+ * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
+ * and uses fourcc codes as pixel format specifiers.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_addfb2(struct drm_device *dev,
+		    void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd2 *r = data;
+	struct drm_framebuffer *fb;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_internal_framebuffer_create(dev, r, file_priv);
+	if (IS_ERR(fb))
+		return PTR_ERR(fb);
+
+	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
+	r->fb_id = fb->base.id;
+
+	/* Transfer ownership to the filp for reaping on close */
+	mutex_lock(&file_priv->fbs_lock);
+	list_add(&fb->filp_head, &file_priv->fbs);
+	mutex_unlock(&file_priv->fbs_lock);
+
+	return 0;
+}
+
+struct drm_mode_rmfb_work {
+	struct work_struct work;
+	struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+	struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+	while (!list_empty(&arg->fbs)) {
+		struct drm_framebuffer *fb =
+			list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+		list_del_init(&fb->filp_head);
+		drm_framebuffer_remove(fb);
+	}
+}
+
+/**
+ * drm_mode_rmfb - remove an FB from the configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Remove the FB specified by the user.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_rmfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_framebuffer *fb = NULL;
+	struct drm_framebuffer *fbl = NULL;
+	uint32_t *id = data;
+	int found = 0;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, *id);
+	if (!fb)
+		return -ENOENT;
+
+	mutex_lock(&file_priv->fbs_lock);
+	list_for_each_entry(fbl, &file_priv->fbs, filp_head)
+		if (fb == fbl)
+			found = 1;
+	if (!found) {
+		mutex_unlock(&file_priv->fbs_lock);
+		goto fail_unref;
+	}
+
+	list_del_init(&fb->filp_head);
+	mutex_unlock(&file_priv->fbs_lock);
+
+	/* drop the reference we picked up in framebuffer lookup */
+	drm_framebuffer_unreference(fb);
+
+	/*
+	 * we now own the reference that was stored in the fbs list
+	 *
+	 * drm_framebuffer_remove may fail with -EINTR on pending signals,
+	 * so run this in a separate stack as there's no way to correctly
+	 * handle this after the fb is already removed from the lookup table.
+	 */
+	if (drm_framebuffer_read_refcount(fb) > 1) {
+		struct drm_mode_rmfb_work arg;
+
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+		INIT_LIST_HEAD(&arg.fbs);
+		list_add_tail(&fb->filp_head, &arg.fbs);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	} else
+		drm_framebuffer_unreference(fb);
+
+	return 0;
+
+fail_unref:
+	drm_framebuffer_unreference(fb);
+	return -ENOENT;
+}
+
+/**
+ * drm_mode_getfb - get FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb(struct drm_device *dev,
+		   void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_fb_cmd *r = data;
+	struct drm_framebuffer *fb;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, r->fb_id);
+	if (!fb)
+		return -ENOENT;
+
+	r->height = fb->height;
+	r->width = fb->width;
+	r->depth = fb->depth;
+	r->bpp = fb->bits_per_pixel;
+	r->pitch = fb->pitches[0];
+	if (fb->funcs->create_handle) {
+		if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
+		    drm_is_control_client(file_priv)) {
+			ret = fb->funcs->create_handle(fb, file_priv,
+						       &r->handle);
+		} else {
+			/* GET_FB() is an unprivileged ioctl so we must not
+			 * return a buffer-handle to non-master processes! For
+			 * backwards-compatibility reasons, we cannot make
+			 * GET_FB() privileged, so just return an invalid handle
+			 * for non-masters. */
+			r->handle = 0;
+			ret = 0;
+		}
+	} else {
+		ret = -ENODEV;
+	}
+
+	drm_framebuffer_unreference(fb);
+
+	return ret;
+}
+
+/**
+ * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB and flush out the damaged area supplied by userspace as a clip
+ * rectangle list. Generic userspace which does frontbuffer rendering must call
+ * this ioctl to flush out the changes on manual-update display outputs, e.g.
+ * usb display-link, mipi manual update panels or edp panel self refresh modes.
+ *
+ * Modesetting drivers which always update the frontbuffer do not need to
+ * implement the corresponding ->dirty framebuffer callback.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
+			   void *data, struct drm_file *file_priv)
+{
+	struct drm_clip_rect __user *clips_ptr;
+	struct drm_clip_rect *clips = NULL;
+	struct drm_mode_fb_dirty_cmd *r = data;
+	struct drm_framebuffer *fb;
+	unsigned flags;
+	int num_clips;
+	int ret;
+
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
+	fb = drm_framebuffer_lookup(dev, r->fb_id);
+	if (!fb)
+		return -ENOENT;
+
+	num_clips = r->num_clips;
+	clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
+
+	if (!num_clips != !clips_ptr) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
+
+	/* If userspace annotates copy, clips must come in pairs */
+	if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
+		ret = -EINVAL;
+		goto out_err1;
+	}
+
+	if (num_clips && clips_ptr) {
+		if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+			ret = -EINVAL;
+			goto out_err1;
+		}
+		clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
+		if (!clips) {
+			ret = -ENOMEM;
+			goto out_err1;
+		}
+
+		ret = copy_from_user(clips, clips_ptr,
+				     num_clips * sizeof(*clips));
+		if (ret) {
+			ret = -EFAULT;
+			goto out_err2;
+		}
+	}
+
+	if (fb->funcs->dirty) {
+		ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
+				       clips, num_clips);
+	} else {
+		ret = -ENOSYS;
+	}
+
+out_err2:
+	kfree(clips);
+out_err1:
+	drm_framebuffer_unreference(fb);
+
+	return ret;
+}
+
+/**
+ * drm_fb_release - remove and free the FBs on this file
+ * @priv: drm file for the ioctl
+ *
+ * Destroy all the FBs associated with @filp.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+void drm_fb_release(struct drm_file *priv)
+{
+	struct drm_framebuffer *fb, *tfb;
+	struct drm_mode_rmfb_work arg;
+
+	INIT_LIST_HEAD(&arg.fbs);
+
+	/*
+	 * When the file gets released that means no one else can access the fb
+	 * list any more, so no need to grab fpriv->fbs_lock. And we need to
+	 * avoid upsetting lockdep since the universal cursor code adds a
+	 * framebuffer while holding mutex locks.
+	 *
+	 * Note that a real deadlock between fpriv->fbs_lock and the modeset
+	 * locks is impossible here since no one else but this function can get
+	 * at it any more.
+	 */
+	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
+		if (drm_framebuffer_read_refcount(fb) > 1) {
+			list_move_tail(&fb->filp_head, &arg.fbs);
+		} else {
+			list_del_init(&fb->filp_head);
+
+			/* This drops the fpriv->fbs reference. */
+			drm_framebuffer_unreference(fb);
+		}
+	}
+
+	if (!list_empty(&arg.fbs)) {
+		INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+		schedule_work(&arg.work);
+		flush_work(&arg.work);
+		destroy_work_on_stack(&arg.work);
+	}
+}
+
+void drm_framebuffer_free(struct kref *kref)
+{
+	struct drm_framebuffer *fb =
+			container_of(kref, struct drm_framebuffer, base.refcount);
+	struct drm_device *dev = fb->dev;
+
+	/*
+	 * The lookup idr holds a weak reference, which has not necessarily been
+	 * removed at this point. Check for that.
+	 */
+	drm_mode_object_unregister(dev, &fb->base);
+
+	fb->funcs->destroy(fb);
+}
+
+/**
+ * drm_framebuffer_init - initialize a framebuffer
+ * @dev: DRM device
+ * @fb: framebuffer to be initialized
+ * @funcs: ... with these functions
+ *
+ * Allocates an ID for the framebuffer's parent mode object, sets its mode
+ * functions & device file and adds it to the master fd list.
+ *
+ * IMPORTANT:
+ * This functions publishes the fb and makes it available for concurrent access
+ * by other users. Which means by this point the fb _must_ be fully set up -
+ * since all the fb attributes are invariant over its lifetime, no further
+ * locking but only correct reference counting is required.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
+			 const struct drm_framebuffer_funcs *funcs)
+{
+	int ret;
+
+	INIT_LIST_HEAD(&fb->filp_head);
+	fb->dev = dev;
+	fb->funcs = funcs;
+
+	ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
+				      false, drm_framebuffer_free);
+	if (ret)
+		goto out;
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	dev->mode_config.num_fb++;
+	list_add(&fb->head, &dev->mode_config.fb_list);
+	mutex_unlock(&dev->mode_config.fb_lock);
+
+	drm_mode_object_register(dev, &fb->base);
+out:
+	return ret;
+}
+EXPORT_SYMBOL(drm_framebuffer_init);
+
+/**
+ * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
+ * @dev: drm device
+ * @id: id of the fb object
+ *
+ * If successful, this grabs an additional reference to the framebuffer -
+ * callers need to make sure to eventually unreference the returned framebuffer
+ * again, using @drm_framebuffer_unreference.
+ */
+struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id)
+{
+	struct drm_mode_object *obj;
+	struct drm_framebuffer *fb = NULL;
+
+	obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB);
+	if (obj)
+		fb = obj_to_fb(obj);
+	return fb;
+}
+EXPORT_SYMBOL(drm_framebuffer_lookup);
+
+/**
+ * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
+ * @fb: fb to unregister
+ *
+ * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
+ * those used for fbdev. Note that the caller must hold a reference of it's own,
+ * i.e. the object may not be destroyed through this call (since it'll lead to a
+ * locking inversion).
+ */
+void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev;
+
+	if (!fb)
+		return;
+
+	dev = fb->dev;
+
+	/* Mark fb as reaped and drop idr ref. */
+	drm_mode_object_unregister(dev, &fb->base);
+}
+EXPORT_SYMBOL(drm_framebuffer_unregister_private);
+
+/**
+ * drm_framebuffer_cleanup - remove a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * Cleanup framebuffer. This function is intended to be used from the drivers
+ * ->destroy callback. It can also be used to clean up driver private
+ * framebuffers embedded into a larger structure.
+ *
+ * Note that this function does not remove the fb from active usuage - if it is
+ * still used anywhere, hilarity can ensue since userspace could call getfb on
+ * the id and get back -EINVAL. Obviously no concern at driver unload time.
+ *
+ * Also, the framebuffer will not be removed from the lookup idr - for
+ * user-created framebuffers this will happen in in the rmfb ioctl. For
+ * driver-private objects (e.g. for fbdev) drivers need to explicitly call
+ * drm_framebuffer_unregister_private.
+ */
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev = fb->dev;
+
+	mutex_lock(&dev->mode_config.fb_lock);
+	list_del(&fb->head);
+	dev->mode_config.num_fb--;
+	mutex_unlock(&dev->mode_config.fb_lock);
+}
+EXPORT_SYMBOL(drm_framebuffer_cleanup);
+
+/**
+ * drm_framebuffer_remove - remove and unreference a framebuffer object
+ * @fb: framebuffer to remove
+ *
+ * Scans all the CRTCs and planes in @dev's mode_config.  If they're
+ * using @fb, removes it, setting it to NULL. Then drops the reference to the
+ * passed-in framebuffer. Might take the modeset locks.
+ *
+ * Note that this function optimizes the cleanup away if the caller holds the
+ * last reference to the framebuffer. It is also guaranteed to not take the
+ * modeset locks in this case.
+ */
+void drm_framebuffer_remove(struct drm_framebuffer *fb)
+{
+	struct drm_device *dev;
+	struct drm_crtc *crtc;
+	struct drm_plane *plane;
+
+	if (!fb)
+		return;
+
+	dev = fb->dev;
+
+	WARN_ON(!list_empty(&fb->filp_head));
+
+	/*
+	 * drm ABI mandates that we remove any deleted framebuffers from active
+	 * useage. But since most sane clients only remove framebuffers they no
+	 * longer need, try to optimize this away.
+	 *
+	 * Since we're holding a reference ourselves, observing a refcount of 1
+	 * means that we're the last holder and can skip it. Also, the refcount
+	 * can never increase from 1 again, so we don't need any barriers or
+	 * locks.
+	 *
+	 * Note that userspace could try to race with use and instate a new
+	 * usage _after_ we've cleared all current ones. End result will be an
+	 * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
+	 * in this manner.
+	 */
+	if (drm_framebuffer_read_refcount(fb) > 1) {
+		if (dev->mode_config.funcs->atomic_commit) {
+			drm_atomic_remove_fb(fb);
+			goto out;
+		}
+
+		drm_modeset_lock_all(dev);
+		/* remove from any CRTC */
+		drm_for_each_crtc(crtc, dev) {
+			if (crtc->primary->fb == fb) {
+				/* should turn off the crtc */
+				if (drm_crtc_force_disable(crtc))
+					DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
+			}
+		}
+
+		drm_for_each_plane(plane, dev) {
+			if (plane->fb == fb)
+				drm_plane_force_disable(plane);
+		}
+		drm_modeset_unlock_all(dev);
+	}
+
+out:
+	drm_framebuffer_unreference(fb);
+}
+EXPORT_SYMBOL(drm_framebuffer_remove);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5a7809f029ba..0119161cad57 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -36,10 +36,12 @@
 #include <uapi/drm/drm_fourcc.h>
 #include <drm/drm_modeset_lock.h>
 #include <drm/drm_rect.h>
+#include <drm/drm_modeset.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_modes.h>
 
 struct drm_device;
 struct drm_mode_set;
-struct drm_framebuffer;
 struct drm_object_properties;
 struct drm_file;
 struct drm_clip_rect;
@@ -47,14 +49,6 @@ struct device_node;
 struct fence;
 struct edid;
 
-struct drm_mode_object {
-	uint32_t id;
-	uint32_t type;
-	struct drm_object_properties *properties;
-	struct kref refcount;
-	void (*free_cb)(struct kref *kref);
-};
-
 #define DRM_OBJECT_MAX_PROPERTY 24
 struct drm_object_properties {
 	int count, atomic_count;
@@ -94,15 +88,6 @@ static inline uint64_t I642U64(int64_t val)
 #define DRM_REFLECT_Y	BIT(5)
 #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
 
-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 */
-};
-
-#include <drm/drm_modes.h>
-
 enum drm_connector_status {
 	connector_status_connected = 1,
 	connector_status_disconnected = 2,
@@ -166,101 +151,6 @@ struct drm_tile_group {
 	u8 group_data[8];
 };
 
-/**
- * struct drm_framebuffer_funcs - framebuffer hooks
- */
-struct drm_framebuffer_funcs {
-	/**
-	 * @destroy:
-	 *
-	 * Clean up framebuffer resources, specifically also unreference the
-	 * backing storage. The core guarantees to call this function for every
-	 * framebuffer successfully created by ->fb_create() in
-	 * &drm_mode_config_funcs. Drivers must also call
-	 * drm_framebuffer_cleanup() to release DRM core resources for this
-	 * framebuffer.
-	 */
-	void (*destroy)(struct drm_framebuffer *framebuffer);
-
-	/**
-	 * @create_handle:
-	 *
-	 * Create a buffer handle in the driver-specific buffer manager (either
-	 * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
-	 * the core to implement the GETFB IOCTL, which returns (for
-	 * sufficiently priviledged user) also a native buffer handle. This can
-	 * be used for seamless transitions between modesetting clients by
-	 * copying the current screen contents to a private buffer and blending
-	 * between that and the new contents.
-	 *
-	 * GEM based drivers should call drm_gem_handle_create() to create the
-	 * handle.
-	 *
-	 * RETURNS:
-	 *
-	 * 0 on success or a negative error code on failure.
-	 */
-	int (*create_handle)(struct drm_framebuffer *fb,
-			     struct drm_file *file_priv,
-			     unsigned int *handle);
-	/**
-	 * @dirty:
-	 *
-	 * Optional callback for the dirty fb IOCTL.
-	 *
-	 * Userspace can notify the driver via this callback that an area of the
-	 * framebuffer has changed and should be flushed to the display
-	 * hardware. This can also be used internally, e.g. by the fbdev
-	 * emulation, though that's not the case currently.
-	 *
-	 * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
-	 * for more information as all the semantics and arguments have a one to
-	 * one mapping on this function.
-	 *
-	 * RETURNS:
-	 *
-	 * 0 on success or a negative error code on failure.
-	 */
-	int (*dirty)(struct drm_framebuffer *framebuffer,
-		     struct drm_file *file_priv, unsigned flags,
-		     unsigned color, struct drm_clip_rect *clips,
-		     unsigned num_clips);
-};
-
-struct drm_framebuffer {
-	struct drm_device *dev;
-	/*
-	 * Note that the fb is refcounted for the benefit of driver internals,
-	 * for example some hw, disabling a CRTC/plane is asynchronous, and
-	 * scanout does not actually complete until the next vblank.  So some
-	 * cleanup (like releasing the reference(s) on the backing GEM bo(s))
-	 * should be deferred.  In cases like this, the driver would like to
-	 * hold a ref to the fb even though it has already been removed from
-	 * userspace perspective.
-	 * The refcount is stored inside the mode object.
-	 */
-	/*
-	 * Place on the dev->mode_config.fb_list, access protected by
-	 * dev->mode_config.fb_lock.
-	 */
-	struct list_head head;
-	struct drm_mode_object base;
-	const struct drm_framebuffer_funcs *funcs;
-	unsigned int pitches[4];
-	unsigned int offsets[4];
-	uint64_t modifier[4];
-	unsigned int width;
-	unsigned int height;
-	/* depth can be 15 or 16 */
-	unsigned int depth;
-	int bits_per_pixel;
-	int flags;
-	uint32_t pixel_format; /* fourcc format */
-	int hot_x;
-	int hot_y;
-	struct list_head filp_head;
-};
-
 struct drm_property_blob {
 	struct drm_mode_object base;
 	struct drm_device *dev;
@@ -2888,14 +2778,6 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,
 extern int drm_object_property_get_value(struct drm_mode_object *obj,
 					 struct drm_property *property,
 					 uint64_t *value);
-extern int drm_framebuffer_init(struct drm_device *dev,
-				struct drm_framebuffer *fb,
-				const struct drm_framebuffer_funcs *funcs);
-extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
-						      uint32_t id);
-extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
-extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
-extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
 
 extern void drm_object_attach_property(struct drm_mode_object *obj,
 				       struct drm_property *property,
@@ -2976,11 +2858,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
 					     unsigned int zpos);
 
 /* Helpers */
-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);
-
 static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
 		uint32_t id)
 {
@@ -3049,39 +2926,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
 }
 
 /**
- * drm_framebuffer_reference - incr the fb refcnt
- * @fb: framebuffer
- *
- * This functions increments the fb's refcount.
- */
-static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
-{
-	drm_mode_object_reference(&fb->base);
-}
-
-/**
- * drm_framebuffer_unreference - unref a framebuffer
- * @fb: framebuffer to unref
- *
- * This functions decrements the fb's refcount and frees it if it drops to zero.
- */
-static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
-{
-	drm_mode_object_unreference(&fb->base);
-}
-
-/**
- * drm_framebuffer_read_refcount - read the framebuffer reference count.
- * @fb: framebuffer
- *
- * This functions returns the framebuffer's reference count.
- */
-static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
-{
-	return atomic_read(&fb->base.refcount.refcount);
-}
-
-/**
  * drm_connector_reference - incr the connector refcnt
  * @connector: connector
  *
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
new file mode 100644
index 000000000000..46abdace8fa5
--- /dev/null
+++ b/include/drm/drm_framebuffer.h
@@ -0,0 +1,170 @@
+/*
+ * 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_FRAMEBUFFER_H__
+#define __DRM_FRAMEBUFFER_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_modeset.h>
+
+struct drm_framebuffer;
+struct drm_file;
+struct drm_device;
+
+/**
+ * struct drm_framebuffer_funcs - framebuffer hooks
+ */
+struct drm_framebuffer_funcs {
+	/**
+	 * @destroy:
+	 *
+	 * Clean up framebuffer resources, specifically also unreference the
+	 * backing storage. The core guarantees to call this function for every
+	 * framebuffer successfully created by ->fb_create() in
+	 * &drm_mode_config_funcs. Drivers must also call
+	 * drm_framebuffer_cleanup() to release DRM core resources for this
+	 * framebuffer.
+	 */
+	void (*destroy)(struct drm_framebuffer *framebuffer);
+
+	/**
+	 * @create_handle:
+	 *
+	 * Create a buffer handle in the driver-specific buffer manager (either
+	 * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
+	 * the core to implement the GETFB IOCTL, which returns (for
+	 * sufficiently priviledged user) also a native buffer handle. This can
+	 * be used for seamless transitions between modesetting clients by
+	 * copying the current screen contents to a private buffer and blending
+	 * between that and the new contents.
+	 *
+	 * GEM based drivers should call drm_gem_handle_create() to create the
+	 * handle.
+	 *
+	 * RETURNS:
+	 *
+	 * 0 on success or a negative error code on failure.
+	 */
+	int (*create_handle)(struct drm_framebuffer *fb,
+			     struct drm_file *file_priv,
+			     unsigned int *handle);
+	/**
+	 * @dirty:
+	 *
+	 * Optional callback for the dirty fb IOCTL.
+	 *
+	 * Userspace can notify the driver via this callback that an area of the
+	 * framebuffer has changed and should be flushed to the display
+	 * hardware. This can also be used internally, e.g. by the fbdev
+	 * emulation, though that's not the case currently.
+	 *
+	 * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
+	 * for more information as all the semantics and arguments have a one to
+	 * one mapping on this function.
+	 *
+	 * RETURNS:
+	 *
+	 * 0 on success or a negative error code on failure.
+	 */
+	int (*dirty)(struct drm_framebuffer *framebuffer,
+		     struct drm_file *file_priv, unsigned flags,
+		     unsigned color, struct drm_clip_rect *clips,
+		     unsigned num_clips);
+};
+
+struct drm_framebuffer {
+	struct drm_device *dev;
+	/*
+	 * Note that the fb is refcounted for the benefit of driver internals,
+	 * for example some hw, disabling a CRTC/plane is asynchronous, and
+	 * scanout does not actually complete until the next vblank.  So some
+	 * cleanup (like releasing the reference(s) on the backing GEM bo(s))
+	 * should be deferred.  In cases like this, the driver would like to
+	 * hold a ref to the fb even though it has already been removed from
+	 * userspace perspective.
+	 * The refcount is stored inside the mode object.
+	 */
+	/*
+	 * Place on the dev->mode_config.fb_list, access protected by
+	 * dev->mode_config.fb_lock.
+	 */
+	struct list_head head;
+	struct drm_mode_object base;
+	const struct drm_framebuffer_funcs *funcs;
+	unsigned int pitches[4];
+	unsigned int offsets[4];
+	uint64_t modifier[4];
+	unsigned int width;
+	unsigned int height;
+	/* depth can be 15 or 16 */
+	unsigned int depth;
+	int bits_per_pixel;
+	int flags;
+	uint32_t pixel_format; /* fourcc format */
+	int hot_x;
+	int hot_y;
+	struct list_head filp_head;
+};
+
+int drm_framebuffer_init(struct drm_device *dev,
+			 struct drm_framebuffer *fb,
+			 const struct drm_framebuffer_funcs *funcs);
+struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+					       uint32_t id);
+void drm_framebuffer_remove(struct drm_framebuffer *fb);
+void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
+void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
+
+/**
+ * drm_framebuffer_reference - incr the fb refcnt
+ * @fb: framebuffer
+ *
+ * This functions increments the fb's refcount.
+ */
+static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
+{
+	drm_mode_object_reference(&fb->base);
+}
+
+/**
+ * drm_framebuffer_unreference - unref a framebuffer
+ * @fb: framebuffer to unref
+ *
+ * This functions decrements the fb's refcount and frees it if it drops to zero.
+ */
+static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
+{
+	drm_mode_object_unreference(&fb->base);
+}
+
+/**
+ * drm_framebuffer_read_refcount - read the framebuffer reference count.
+ * @fb: framebuffer
+ *
+ * This functions returns the framebuffer's reference count.
+ */
+static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
+{
+	return atomic_read(&fb->base.refcount.refcount);
+}
+#endif
diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
index 48e1a56ea283..fed9fe81590c 100644
--- a/include/drm/drm_modes.h
+++ b/include/drm/drm_modes.h
@@ -27,6 +27,8 @@
 #ifndef __DRM_MODES_H__
 #define __DRM_MODES_H__
 
+#include <drm/drm_modeset.h>
+
 /*
  * Note on terminology:  here, for brevity and convenience, we refer to connector
  * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
diff --git a/include/drm/drm_modeset.h b/include/drm/drm_modeset.h
new file mode 100644
index 000000000000..0c2b0f3c5f34
--- /dev/null
+++ b/include/drm/drm_modeset.h
@@ -0,0 +1,50 @@
+/*
+ * 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_MODESET_H__
+#define __DRM_MODESET_H__
+
+#include <linux/kref.h>
+struct drm_object_properties;
+
+struct drm_mode_object {
+	uint32_t id;
+	uint32_t type;
+	struct drm_object_properties *properties;
+	struct kref refcount;
+	void (*free_cb)(struct kref *kref);
+};
+
+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

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c
  2016-08-12 20:48 ` [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c Daniel Vetter
@ 2016-08-15 20:14   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:14 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Ville ocd'ed the parameter name, but forgot to update the docs!
>
> Fixes: df86af9133b4 ("drm/plane-helper: Add drm_plane_helper_check_state()")
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  drivers/gpu/drm/drm_plane_helper.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 50b9c1bfc6f6..7899fc1dcdb0 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -199,7 +199,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_state);
>   * @crtc: owning CRTC of owning plane
>   * @fb: framebuffer to flip onto plane
>   * @src: source coordinates in 16.16 fixed point
> - * @dest: integer destination coordinates
> + * @dst: integer destination coordinates
>   * @clip: integer clipping coordinates
>   * @rotation: plane rotation
>   * @min_scale: minimum @src:@dest scaling factor in 16.16 fixed point
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH] drm: Extract drm_framebuffer.[hc]
  2016-08-15 14:07   ` [PATCH] " Daniel Vetter
@ 2016-08-15 20:15     ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: DRI Development

On Mon, Aug 15, 2016 at 10:07 AM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Also start with drm_modeset.h with the core bits, since we need
> to untangle this mess somehow. That allows us to move the drm_modes.h
> include to the right spot, except for the temporary connector status
> enum. That will get fixed as soon as drm_connector.h exists.
>
> v2: Rebase.
>
> v3: Move drm_crtc_force_disable_all back again, that wasn't meant to
> be moved (Sean).
>
> v4: Rebase.
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/drm-kms.rst       |   9 +
>  drivers/gpu/drm/Makefile            |   3 +-
>  drivers/gpu/drm/drm_crtc.c          | 807 +-----------------------------------
>  drivers/gpu/drm/drm_crtc_internal.h |  40 +-
>  drivers/gpu/drm/drm_framebuffer.c   | 799 +++++++++++++++++++++++++++++++++++
>  include/drm/drm_crtc.h              | 162 +-------
>  include/drm/drm_framebuffer.h       | 170 ++++++++
>  include/drm/drm_modes.h             |   2 +
>  include/drm/drm_modeset.h           |  50 +++
>  9 files changed, 1078 insertions(+), 964 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_framebuffer.c
>  create mode 100644 include/drm/drm_framebuffer.h
>  create mode 100644 include/drm/drm_modeset.h
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 3ae4c12aca08..8264a88a8695 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -64,6 +64,15 @@ fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
>  drivers can manually clean up a framebuffer at module unload time with
>  :c:func:`drm_framebuffer_unregister_private()`.
>
> +Frame Buffer Functions Reference
> +--------------------------------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
> +   :export:
> +
> +.. kernel-doc:: include/drm/drm_framebuffer.h
> +   :internal:
> +
>  DRM Format Handling
>  ===================
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index a5824d926dc9..c71ec42ce511 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -12,7 +12,8 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.o \
>                 drm_info.o drm_debugfs.o drm_encoder_slave.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_modeset_lock.o drm_atomic.o drm_bridge.o \
> +               drm_framebuffer.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_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 4499126321e0..b38dd10841e6 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -40,15 +40,11 @@
>  #include <drm/drm_modeset_lock.h>
>  #include <drm/drm_atomic.h>
>  #include <drm/drm_auth.h>
> +#include <drm/drm_framebuffer.h>
>
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
>
> -static struct drm_framebuffer *
> -internal_framebuffer_create(struct drm_device *dev,
> -                           const struct drm_mode_fb_cmd2 *r,
> -                           struct drm_file *file_priv);
> -
>  /* Avoid boilerplate.  I'm tired of typing. */
>  #define DRM_ENUM_NAME_FN(fnname, list)                         \
>         const char *fnname(int val)                             \
> @@ -238,11 +234,11 @@ 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.
>   */
> -static int drm_mode_object_get_reg(struct drm_device *dev,
> -                                  struct drm_mode_object *obj,
> -                                  uint32_t obj_type,
> -                                  bool register_obj,
> -                                  void (*obj_free_cb)(struct kref *kref))
> +int drm_mode_object_get_reg(struct drm_device *dev,
> +                           struct drm_mode_object *obj,
> +                           uint32_t obj_type,
> +                           bool register_obj,
> +                           void (*obj_free_cb)(struct kref *kref))
>  {
>         int ret;
>
> @@ -285,8 +281,8 @@ int drm_mode_object_get(struct drm_device *dev,
>         return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
>  }
>
> -static void drm_mode_object_register(struct drm_device *dev,
> -                                    struct drm_mode_object *obj)
> +void drm_mode_object_register(struct drm_device *dev,
> +                             struct drm_mode_object *obj)
>  {
>         mutex_lock(&dev->mode_config.idr_mutex);
>         idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
> @@ -315,8 +311,8 @@ void drm_mode_object_unregister(struct drm_device *dev,
>         mutex_unlock(&dev->mode_config.idr_mutex);
>  }
>
> -static struct drm_mode_object *_object_find(struct drm_device *dev,
> -               uint32_t id, uint32_t type)
> +struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
> +                                              uint32_t id, uint32_t type)
>  {
>         struct drm_mode_object *obj = NULL;
>
> @@ -351,7 +347,7 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
>  {
>         struct drm_mode_object *obj = NULL;
>
> -       obj = _object_find(dev, id, type);
> +       obj = __drm_mode_object_find(dev, id, type);
>         return obj;
>  }
>  EXPORT_SYMBOL(drm_mode_object_find);
> @@ -435,205 +431,6 @@ out:
>  }
>  EXPORT_SYMBOL(drm_crtc_force_disable_all);
>
> -static void drm_framebuffer_free(struct kref *kref)
> -{
> -       struct drm_framebuffer *fb =
> -                       container_of(kref, struct drm_framebuffer, base.refcount);
> -       struct drm_device *dev = fb->dev;
> -
> -       /*
> -        * The lookup idr holds a weak reference, which has not necessarily been
> -        * removed at this point. Check for that.
> -        */
> -       drm_mode_object_unregister(dev, &fb->base);
> -
> -       fb->funcs->destroy(fb);
> -}
> -
> -/**
> - * drm_framebuffer_init - initialize a framebuffer
> - * @dev: DRM device
> - * @fb: framebuffer to be initialized
> - * @funcs: ... with these functions
> - *
> - * Allocates an ID for the framebuffer's parent mode object, sets its mode
> - * functions & device file and adds it to the master fd list.
> - *
> - * IMPORTANT:
> - * This functions publishes the fb and makes it available for concurrent access
> - * by other users. Which means by this point the fb _must_ be fully set up -
> - * since all the fb attributes are invariant over its lifetime, no further
> - * locking but only correct reference counting is required.
> - *
> - * Returns:
> - * Zero on success, error code on failure.
> - */
> -int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
> -                        const struct drm_framebuffer_funcs *funcs)
> -{
> -       int ret;
> -
> -       INIT_LIST_HEAD(&fb->filp_head);
> -       fb->dev = dev;
> -       fb->funcs = funcs;
> -
> -       ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
> -                                     false, drm_framebuffer_free);
> -       if (ret)
> -               goto out;
> -
> -       mutex_lock(&dev->mode_config.fb_lock);
> -       dev->mode_config.num_fb++;
> -       list_add(&fb->head, &dev->mode_config.fb_list);
> -       mutex_unlock(&dev->mode_config.fb_lock);
> -
> -       drm_mode_object_register(dev, &fb->base);
> -out:
> -       return ret;
> -}
> -EXPORT_SYMBOL(drm_framebuffer_init);
> -
> -/**
> - * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
> - * @dev: drm device
> - * @id: id of the fb object
> - *
> - * If successful, this grabs an additional reference to the framebuffer -
> - * callers need to make sure to eventually unreference the returned framebuffer
> - * again, using @drm_framebuffer_unreference.
> - */
> -struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
> -                                              uint32_t id)
> -{
> -       struct drm_mode_object *obj;
> -       struct drm_framebuffer *fb = NULL;
> -
> -       obj = _object_find(dev, id, DRM_MODE_OBJECT_FB);
> -       if (obj)
> -               fb = obj_to_fb(obj);
> -       return fb;
> -}
> -EXPORT_SYMBOL(drm_framebuffer_lookup);
> -
> -/**
> - * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
> - * @fb: fb to unregister
> - *
> - * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
> - * those used for fbdev. Note that the caller must hold a reference of it's own,
> - * i.e. the object may not be destroyed through this call (since it'll lead to a
> - * locking inversion).
> - */
> -void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
> -{
> -       struct drm_device *dev;
> -
> -       if (!fb)
> -               return;
> -
> -       dev = fb->dev;
> -
> -       /* Mark fb as reaped and drop idr ref. */
> -       drm_mode_object_unregister(dev, &fb->base);
> -}
> -EXPORT_SYMBOL(drm_framebuffer_unregister_private);
> -
> -/**
> - * drm_framebuffer_cleanup - remove a framebuffer object
> - * @fb: framebuffer to remove
> - *
> - * Cleanup framebuffer. This function is intended to be used from the drivers
> - * ->destroy callback. It can also be used to clean up driver private
> - * framebuffers embedded into a larger structure.
> - *
> - * Note that this function does not remove the fb from active usuage - if it is
> - * still used anywhere, hilarity can ensue since userspace could call getfb on
> - * the id and get back -EINVAL. Obviously no concern at driver unload time.
> - *
> - * Also, the framebuffer will not be removed from the lookup idr - for
> - * user-created framebuffers this will happen in in the rmfb ioctl. For
> - * driver-private objects (e.g. for fbdev) drivers need to explicitly call
> - * drm_framebuffer_unregister_private.
> - */
> -void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
> -{
> -       struct drm_device *dev = fb->dev;
> -
> -       mutex_lock(&dev->mode_config.fb_lock);
> -       list_del(&fb->head);
> -       dev->mode_config.num_fb--;
> -       mutex_unlock(&dev->mode_config.fb_lock);
> -}
> -EXPORT_SYMBOL(drm_framebuffer_cleanup);
> -
> -/**
> - * drm_framebuffer_remove - remove and unreference a framebuffer object
> - * @fb: framebuffer to remove
> - *
> - * Scans all the CRTCs and planes in @dev's mode_config.  If they're
> - * using @fb, removes it, setting it to NULL. Then drops the reference to the
> - * passed-in framebuffer. Might take the modeset locks.
> - *
> - * Note that this function optimizes the cleanup away if the caller holds the
> - * last reference to the framebuffer. It is also guaranteed to not take the
> - * modeset locks in this case.
> - */
> -void drm_framebuffer_remove(struct drm_framebuffer *fb)
> -{
> -       struct drm_device *dev;
> -       struct drm_crtc *crtc;
> -       struct drm_plane *plane;
> -
> -       if (!fb)
> -               return;
> -
> -       dev = fb->dev;
> -
> -       WARN_ON(!list_empty(&fb->filp_head));
> -
> -       /*
> -        * drm ABI mandates that we remove any deleted framebuffers from active
> -        * useage. But since most sane clients only remove framebuffers they no
> -        * longer need, try to optimize this away.
> -        *
> -        * Since we're holding a reference ourselves, observing a refcount of 1
> -        * means that we're the last holder and can skip it. Also, the refcount
> -        * can never increase from 1 again, so we don't need any barriers or
> -        * locks.
> -        *
> -        * Note that userspace could try to race with use and instate a new
> -        * usage _after_ we've cleared all current ones. End result will be an
> -        * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
> -        * in this manner.
> -        */
> -       if (drm_framebuffer_read_refcount(fb) > 1) {
> -               if (dev->mode_config.funcs->atomic_commit) {
> -                       drm_atomic_remove_fb(fb);
> -                       goto out;
> -               }
> -
> -               drm_modeset_lock_all(dev);
> -               /* remove from any CRTC */
> -               drm_for_each_crtc(crtc, dev) {
> -                       if (crtc->primary->fb == fb) {
> -                               /* should turn off the crtc */
> -                               if (drm_crtc_force_disable(crtc))
> -                                       DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
> -                       }
> -               }
> -
> -               drm_for_each_plane(plane, dev) {
> -                       if (plane->fb == fb)
> -                               drm_plane_force_disable(plane);
> -               }
> -               drm_modeset_unlock_all(dev);
> -       }
> -
> -out:
> -       drm_framebuffer_unreference(fb);
> -}
> -EXPORT_SYMBOL(drm_framebuffer_remove);
> -
>  DEFINE_WW_CLASS(crtc_ww_class);
>
>  static unsigned int drm_num_crtcs(struct drm_device *dev)
> @@ -3012,7 +2809,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
>          */
>         if (req->flags & DRM_MODE_CURSOR_BO) {
>                 if (req->handle) {
> -                       fb = internal_framebuffer_create(dev, &fbreq, file_priv);
> +                       fb = drm_internal_framebuffer_create(dev, &fbreq, file_priv);
>                         if (IS_ERR(fb)) {
>                                 DRM_DEBUG_KMS("failed to wrap cursor buffer in drm framebuffer\n");
>                                 return PTR_ERR(fb);
> @@ -3210,581 +3007,6 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
>  }
>  EXPORT_SYMBOL(drm_mode_legacy_fb_format);
>
> -/**
> - * drm_mode_addfb - add an FB to the graphics configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Add a new FB to the specified CRTC, given a user request. This is the
> - * original addfb ioctl which only supported RGB formats.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_addfb(struct drm_device *dev,
> -                  void *data, struct drm_file *file_priv)
> -{
> -       struct drm_mode_fb_cmd *or = data;
> -       struct drm_mode_fb_cmd2 r = {};
> -       int ret;
> -
> -       /* convert to new format and call new ioctl */
> -       r.fb_id = or->fb_id;
> -       r.width = or->width;
> -       r.height = or->height;
> -       r.pitches[0] = or->pitch;
> -       r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
> -       r.handles[0] = or->handle;
> -
> -       ret = drm_mode_addfb2(dev, &r, file_priv);
> -       if (ret)
> -               return ret;
> -
> -       or->fb_id = r.fb_id;
> -
> -       return 0;
> -}
> -
> -static int format_check(const struct drm_mode_fb_cmd2 *r)
> -{
> -       uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
> -       const char *format_name;
> -
> -       switch (format) {
> -       case DRM_FORMAT_C8:
> -       case DRM_FORMAT_RGB332:
> -       case DRM_FORMAT_BGR233:
> -       case DRM_FORMAT_XRGB4444:
> -       case DRM_FORMAT_XBGR4444:
> -       case DRM_FORMAT_RGBX4444:
> -       case DRM_FORMAT_BGRX4444:
> -       case DRM_FORMAT_ARGB4444:
> -       case DRM_FORMAT_ABGR4444:
> -       case DRM_FORMAT_RGBA4444:
> -       case DRM_FORMAT_BGRA4444:
> -       case DRM_FORMAT_XRGB1555:
> -       case DRM_FORMAT_XBGR1555:
> -       case DRM_FORMAT_RGBX5551:
> -       case DRM_FORMAT_BGRX5551:
> -       case DRM_FORMAT_ARGB1555:
> -       case DRM_FORMAT_ABGR1555:
> -       case DRM_FORMAT_RGBA5551:
> -       case DRM_FORMAT_BGRA5551:
> -       case DRM_FORMAT_RGB565:
> -       case DRM_FORMAT_BGR565:
> -       case DRM_FORMAT_RGB888:
> -       case DRM_FORMAT_BGR888:
> -       case DRM_FORMAT_XRGB8888:
> -       case DRM_FORMAT_XBGR8888:
> -       case DRM_FORMAT_RGBX8888:
> -       case DRM_FORMAT_BGRX8888:
> -       case DRM_FORMAT_ARGB8888:
> -       case DRM_FORMAT_ABGR8888:
> -       case DRM_FORMAT_RGBA8888:
> -       case DRM_FORMAT_BGRA8888:
> -       case DRM_FORMAT_XRGB2101010:
> -       case DRM_FORMAT_XBGR2101010:
> -       case DRM_FORMAT_RGBX1010102:
> -       case DRM_FORMAT_BGRX1010102:
> -       case DRM_FORMAT_ARGB2101010:
> -       case DRM_FORMAT_ABGR2101010:
> -       case DRM_FORMAT_RGBA1010102:
> -       case DRM_FORMAT_BGRA1010102:
> -       case DRM_FORMAT_YUYV:
> -       case DRM_FORMAT_YVYU:
> -       case DRM_FORMAT_UYVY:
> -       case DRM_FORMAT_VYUY:
> -       case DRM_FORMAT_AYUV:
> -       case DRM_FORMAT_NV12:
> -       case DRM_FORMAT_NV21:
> -       case DRM_FORMAT_NV16:
> -       case DRM_FORMAT_NV61:
> -       case DRM_FORMAT_NV24:
> -       case DRM_FORMAT_NV42:
> -       case DRM_FORMAT_YUV410:
> -       case DRM_FORMAT_YVU410:
> -       case DRM_FORMAT_YUV411:
> -       case DRM_FORMAT_YVU411:
> -       case DRM_FORMAT_YUV420:
> -       case DRM_FORMAT_YVU420:
> -       case DRM_FORMAT_YUV422:
> -       case DRM_FORMAT_YVU422:
> -       case DRM_FORMAT_YUV444:
> -       case DRM_FORMAT_YVU444:
> -               return 0;
> -       default:
> -               format_name = drm_get_format_name(r->pixel_format);
> -               DRM_DEBUG_KMS("invalid pixel format %s\n", format_name);
> -               kfree(format_name);
> -               return -EINVAL;
> -       }
> -}
> -
> -static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
> -{
> -       int ret, hsub, vsub, num_planes, i;
> -
> -       ret = format_check(r);
> -       if (ret) {
> -               const char *format_name = drm_get_format_name(r->pixel_format);
> -               DRM_DEBUG_KMS("bad framebuffer format %s\n", format_name);
> -               kfree(format_name);
> -               return ret;
> -       }
> -
> -       hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
> -       vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
> -       num_planes = drm_format_num_planes(r->pixel_format);
> -
> -       if (r->width == 0 || r->width % hsub) {
> -               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
> -               return -EINVAL;
> -       }
> -
> -       if (r->height == 0 || r->height % vsub) {
> -               DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
> -               return -EINVAL;
> -       }
> -
> -       for (i = 0; i < num_planes; i++) {
> -               unsigned int width = r->width / (i != 0 ? hsub : 1);
> -               unsigned int height = r->height / (i != 0 ? vsub : 1);
> -               unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
> -
> -               if (!r->handles[i]) {
> -                       DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
> -                       return -EINVAL;
> -               }
> -
> -               if ((uint64_t) width * cpp > UINT_MAX)
> -                       return -ERANGE;
> -
> -               if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
> -                       return -ERANGE;
> -
> -               if (r->pitches[i] < width * cpp) {
> -                       DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
> -                       return -EINVAL;
> -               }
> -
> -               if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
> -                       DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
> -                                     r->modifier[i], i);
> -                       return -EINVAL;
> -               }
> -
> -               /* modifier specific checks: */
> -               switch (r->modifier[i]) {
> -               case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
> -                       /* NOTE: the pitch restriction may be lifted later if it turns
> -                        * out that no hw has this restriction:
> -                        */
> -                       if (r->pixel_format != DRM_FORMAT_NV12 ||
> -                                       width % 128 || height % 32 ||
> -                                       r->pitches[i] % 128) {
> -                               DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
> -                               return -EINVAL;
> -                       }
> -                       break;
> -
> -               default:
> -                       break;
> -               }
> -       }
> -
> -       for (i = num_planes; i < 4; i++) {
> -               if (r->modifier[i]) {
> -                       DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
> -                       return -EINVAL;
> -               }
> -
> -               /* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
> -               if (!(r->flags & DRM_MODE_FB_MODIFIERS))
> -                       continue;
> -
> -               if (r->handles[i]) {
> -                       DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
> -                       return -EINVAL;
> -               }
> -
> -               if (r->pitches[i]) {
> -                       DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
> -                       return -EINVAL;
> -               }
> -
> -               if (r->offsets[i]) {
> -                       DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
> -                       return -EINVAL;
> -               }
> -       }
> -
> -       return 0;
> -}
> -
> -static struct drm_framebuffer *
> -internal_framebuffer_create(struct drm_device *dev,
> -                           const struct drm_mode_fb_cmd2 *r,
> -                           struct drm_file *file_priv)
> -{
> -       struct drm_mode_config *config = &dev->mode_config;
> -       struct drm_framebuffer *fb;
> -       int ret;
> -
> -       if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
> -               DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
> -               return ERR_PTR(-EINVAL);
> -       }
> -
> -       if ((config->min_width > r->width) || (r->width > config->max_width)) {
> -               DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
> -                         r->width, config->min_width, config->max_width);
> -               return ERR_PTR(-EINVAL);
> -       }
> -       if ((config->min_height > r->height) || (r->height > config->max_height)) {
> -               DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
> -                         r->height, config->min_height, config->max_height);
> -               return ERR_PTR(-EINVAL);
> -       }
> -
> -       if (r->flags & DRM_MODE_FB_MODIFIERS &&
> -           !dev->mode_config.allow_fb_modifiers) {
> -               DRM_DEBUG_KMS("driver does not support fb modifiers\n");
> -               return ERR_PTR(-EINVAL);
> -       }
> -
> -       ret = framebuffer_check(r);
> -       if (ret)
> -               return ERR_PTR(ret);
> -
> -       fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
> -       if (IS_ERR(fb)) {
> -               DRM_DEBUG_KMS("could not create framebuffer\n");
> -               return fb;
> -       }
> -
> -       return fb;
> -}
> -
> -/**
> - * drm_mode_addfb2 - add an FB to the graphics configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Add a new FB to the specified CRTC, given a user request with format. This is
> - * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
> - * and uses fourcc codes as pixel format specifiers.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_addfb2(struct drm_device *dev,
> -                   void *data, struct drm_file *file_priv)
> -{
> -       struct drm_mode_fb_cmd2 *r = data;
> -       struct drm_framebuffer *fb;
> -
> -       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> -               return -EINVAL;
> -
> -       fb = internal_framebuffer_create(dev, r, file_priv);
> -       if (IS_ERR(fb))
> -               return PTR_ERR(fb);
> -
> -       DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
> -       r->fb_id = fb->base.id;
> -
> -       /* Transfer ownership to the filp for reaping on close */
> -       mutex_lock(&file_priv->fbs_lock);
> -       list_add(&fb->filp_head, &file_priv->fbs);
> -       mutex_unlock(&file_priv->fbs_lock);
> -
> -       return 0;
> -}
> -
> -struct drm_mode_rmfb_work {
> -       struct work_struct work;
> -       struct list_head fbs;
> -};
> -
> -static void drm_mode_rmfb_work_fn(struct work_struct *w)
> -{
> -       struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
> -
> -       while (!list_empty(&arg->fbs)) {
> -               struct drm_framebuffer *fb =
> -                       list_first_entry(&arg->fbs, typeof(*fb), filp_head);
> -
> -               list_del_init(&fb->filp_head);
> -               drm_framebuffer_remove(fb);
> -       }
> -}
> -
> -/**
> - * drm_mode_rmfb - remove an FB from the configuration
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Remove the FB specified by the user.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_rmfb(struct drm_device *dev,
> -                  void *data, struct drm_file *file_priv)
> -{
> -       struct drm_framebuffer *fb = NULL;
> -       struct drm_framebuffer *fbl = NULL;
> -       uint32_t *id = data;
> -       int found = 0;
> -
> -       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> -               return -EINVAL;
> -
> -       fb = drm_framebuffer_lookup(dev, *id);
> -       if (!fb)
> -               return -ENOENT;
> -
> -       mutex_lock(&file_priv->fbs_lock);
> -       list_for_each_entry(fbl, &file_priv->fbs, filp_head)
> -               if (fb == fbl)
> -                       found = 1;
> -       if (!found) {
> -               mutex_unlock(&file_priv->fbs_lock);
> -               goto fail_unref;
> -       }
> -
> -       list_del_init(&fb->filp_head);
> -       mutex_unlock(&file_priv->fbs_lock);
> -
> -       /* drop the reference we picked up in framebuffer lookup */
> -       drm_framebuffer_unreference(fb);
> -
> -       /*
> -        * we now own the reference that was stored in the fbs list
> -        *
> -        * drm_framebuffer_remove may fail with -EINTR on pending signals,
> -        * so run this in a separate stack as there's no way to correctly
> -        * handle this after the fb is already removed from the lookup table.
> -        */
> -       if (drm_framebuffer_read_refcount(fb) > 1) {
> -               struct drm_mode_rmfb_work arg;
> -
> -               INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
> -               INIT_LIST_HEAD(&arg.fbs);
> -               list_add_tail(&fb->filp_head, &arg.fbs);
> -
> -               schedule_work(&arg.work);
> -               flush_work(&arg.work);
> -               destroy_work_on_stack(&arg.work);
> -       } else
> -               drm_framebuffer_unreference(fb);
> -
> -       return 0;
> -
> -fail_unref:
> -       drm_framebuffer_unreference(fb);
> -       return -ENOENT;
> -}
> -
> -/**
> - * drm_mode_getfb - get FB info
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Lookup the FB given its ID and return info about it.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_getfb(struct drm_device *dev,
> -                  void *data, struct drm_file *file_priv)
> -{
> -       struct drm_mode_fb_cmd *r = data;
> -       struct drm_framebuffer *fb;
> -       int ret;
> -
> -       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> -               return -EINVAL;
> -
> -       fb = drm_framebuffer_lookup(dev, r->fb_id);
> -       if (!fb)
> -               return -ENOENT;
> -
> -       r->height = fb->height;
> -       r->width = fb->width;
> -       r->depth = fb->depth;
> -       r->bpp = fb->bits_per_pixel;
> -       r->pitch = fb->pitches[0];
> -       if (fb->funcs->create_handle) {
> -               if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
> -                   drm_is_control_client(file_priv)) {
> -                       ret = fb->funcs->create_handle(fb, file_priv,
> -                                                      &r->handle);
> -               } else {
> -                       /* GET_FB() is an unprivileged ioctl so we must not
> -                        * return a buffer-handle to non-master processes! For
> -                        * backwards-compatibility reasons, we cannot make
> -                        * GET_FB() privileged, so just return an invalid handle
> -                        * for non-masters. */
> -                       r->handle = 0;
> -                       ret = 0;
> -               }
> -       } else {
> -               ret = -ENODEV;
> -       }
> -
> -       drm_framebuffer_unreference(fb);
> -
> -       return ret;
> -}
> -
> -/**
> - * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
> - * @dev: drm device for the ioctl
> - * @data: data pointer for the ioctl
> - * @file_priv: drm file for the ioctl call
> - *
> - * Lookup the FB and flush out the damaged area supplied by userspace as a clip
> - * rectangle list. Generic userspace which does frontbuffer rendering must call
> - * this ioctl to flush out the changes on manual-update display outputs, e.g.
> - * usb display-link, mipi manual update panels or edp panel self refresh modes.
> - *
> - * Modesetting drivers which always update the frontbuffer do not need to
> - * implement the corresponding ->dirty framebuffer callback.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
> -                          void *data, struct drm_file *file_priv)
> -{
> -       struct drm_clip_rect __user *clips_ptr;
> -       struct drm_clip_rect *clips = NULL;
> -       struct drm_mode_fb_dirty_cmd *r = data;
> -       struct drm_framebuffer *fb;
> -       unsigned flags;
> -       int num_clips;
> -       int ret;
> -
> -       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> -               return -EINVAL;
> -
> -       fb = drm_framebuffer_lookup(dev, r->fb_id);
> -       if (!fb)
> -               return -ENOENT;
> -
> -       num_clips = r->num_clips;
> -       clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
> -
> -       if (!num_clips != !clips_ptr) {
> -               ret = -EINVAL;
> -               goto out_err1;
> -       }
> -
> -       flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
> -
> -       /* If userspace annotates copy, clips must come in pairs */
> -       if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
> -               ret = -EINVAL;
> -               goto out_err1;
> -       }
> -
> -       if (num_clips && clips_ptr) {
> -               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
> -                       ret = -EINVAL;
> -                       goto out_err1;
> -               }
> -               clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
> -               if (!clips) {
> -                       ret = -ENOMEM;
> -                       goto out_err1;
> -               }
> -
> -               ret = copy_from_user(clips, clips_ptr,
> -                                    num_clips * sizeof(*clips));
> -               if (ret) {
> -                       ret = -EFAULT;
> -                       goto out_err2;
> -               }
> -       }
> -
> -       if (fb->funcs->dirty) {
> -               ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
> -                                      clips, num_clips);
> -       } else {
> -               ret = -ENOSYS;
> -       }
> -
> -out_err2:
> -       kfree(clips);
> -out_err1:
> -       drm_framebuffer_unreference(fb);
> -
> -       return ret;
> -}
> -
> -/**
> - * drm_fb_release - remove and free the FBs on this file
> - * @priv: drm file for the ioctl
> - *
> - * Destroy all the FBs associated with @filp.
> - *
> - * Called by the user via ioctl.
> - *
> - * Returns:
> - * Zero on success, negative errno on failure.
> - */
> -void drm_fb_release(struct drm_file *priv)
> -{
> -       struct drm_framebuffer *fb, *tfb;
> -       struct drm_mode_rmfb_work arg;
> -
> -       INIT_LIST_HEAD(&arg.fbs);
> -
> -       /*
> -        * When the file gets released that means no one else can access the fb
> -        * list any more, so no need to grab fpriv->fbs_lock. And we need to
> -        * avoid upsetting lockdep since the universal cursor code adds a
> -        * framebuffer while holding mutex locks.
> -        *
> -        * Note that a real deadlock between fpriv->fbs_lock and the modeset
> -        * locks is impossible here since no one else but this function can get
> -        * at it any more.
> -        */
> -       list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
> -               if (drm_framebuffer_read_refcount(fb) > 1) {
> -                       list_move_tail(&fb->filp_head, &arg.fbs);
> -               } else {
> -                       list_del_init(&fb->filp_head);
> -
> -                       /* This drops the fpriv->fbs reference. */
> -                       drm_framebuffer_unreference(fb);
> -               }
> -       }
> -
> -       if (!list_empty(&arg.fbs)) {
> -               INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
> -
> -               schedule_work(&arg.work);
> -               flush_work(&arg.work);
> -               destroy_work_on_stack(&arg.work);
> -       }
> -}
> -
>  static bool drm_property_type_valid(struct drm_property *property)
>  {
>         if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> @@ -4497,7 +3719,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
>         struct drm_mode_object *obj;
>         struct drm_property_blob *blob = NULL;
>
> -       obj = _object_find(dev, id, DRM_MODE_OBJECT_BLOB);
> +       obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
>         if (obj)
>                 blob = obj_to_blob(obj);
>         return blob;
> @@ -4893,7 +4115,8 @@ bool drm_property_change_valid_get(struct drm_property *property,
>                 if (value == 0)
>                         return true;
>
> -               *ref = _object_find(property->dev, value, property->values[0]);
> +               *ref = __drm_mode_object_find(property->dev, value,
> +                                             property->values[0]);
>                 return *ref != NULL;
>         }
>
> diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
> index 3ea72e1780b1..5f1e9ff71ae4 100644
> --- a/drivers/gpu/drm/drm_crtc_internal.h
> +++ b/drivers/gpu/drm/drm_crtc_internal.h
> @@ -35,8 +35,17 @@
>  /* 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,
> +                           bool register_obj,
> +                           void (*obj_free_cb)(struct kref *kref));
> +void drm_mode_object_register(struct drm_device *dev,
> +                             struct drm_mode_object *obj);
>  int drm_mode_object_get(struct drm_device *dev,
>                         struct drm_mode_object *obj, uint32_t obj_type);
> +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);
>  bool drm_property_change_valid_get(struct drm_property *property,
> @@ -64,18 +73,6 @@ int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
>  int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
>                                 void *data, struct drm_file *file_priv);
>
> -/* framebuffer IOCTLs */
> -extern int drm_mode_addfb(struct drm_device *dev,
> -                         void *data, struct drm_file *file_priv);
> -extern int drm_mode_addfb2(struct drm_device *dev,
> -                          void *data, struct drm_file *file_priv);
> -int drm_mode_rmfb(struct drm_device *dev,
> -                        void *data, struct drm_file *file_priv);
> -int drm_mode_getfb(struct drm_device *dev,
> -                  void *data, struct drm_file *file_priv);
> -int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
> -                          void *data, struct drm_file *file_priv);
> -
>  /* IOCTLs */
>  int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
>                                       struct drm_file *file_priv);
> @@ -120,6 +117,25 @@ 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_framebuffer.c */
> +struct drm_framebuffer *
> +drm_internal_framebuffer_create(struct drm_device *dev,
> +                               const struct drm_mode_fb_cmd2 *r,
> +                               struct drm_file *file_priv);
> +void drm_framebuffer_free(struct kref *kref);
> +
> +/* IOCTL */
> +int drm_mode_addfb(struct drm_device *dev,
> +                  void *data, struct drm_file *file_priv);
> +int drm_mode_addfb2(struct drm_device *dev,
> +                   void *data, struct drm_file *file_priv);
> +int drm_mode_rmfb(struct drm_device *dev,
> +                 void *data, struct drm_file *file_priv);
> +int drm_mode_getfb(struct drm_device *dev,
> +                  void *data, struct drm_file *file_priv);
> +int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
> +                          void *data, struct drm_file *file_priv);
> +
>  /* drm_atomic.c */
>  int drm_atomic_get_property(struct drm_mode_object *obj,
>                             struct drm_property *property, uint64_t *val);
> diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> new file mode 100644
> index 000000000000..19478a25ac20
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -0,0 +1,799 @@
> +/*
> + * 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 <linux/export.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_auth.h>
> +#include <drm/drm_framebuffer.h>
> +
> +#include "drm_crtc_internal.h"
> +
> +/**
> + * drm_mode_addfb - add an FB to the graphics configuration
> + * @dev: drm device for the ioctl
> + * @data: data pointer for the ioctl
> + * @file_priv: drm file for the ioctl call
> + *
> + * Add a new FB to the specified CRTC, given a user request. This is the
> + * original addfb ioctl which only supported RGB formats.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_addfb(struct drm_device *dev,
> +                  void *data, struct drm_file *file_priv)
> +{
> +       struct drm_mode_fb_cmd *or = data;
> +       struct drm_mode_fb_cmd2 r = {};
> +       int ret;
> +
> +       /* convert to new format and call new ioctl */
> +       r.fb_id = or->fb_id;
> +       r.width = or->width;
> +       r.height = or->height;
> +       r.pitches[0] = or->pitch;
> +       r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
> +       r.handles[0] = or->handle;
> +
> +       ret = drm_mode_addfb2(dev, &r, file_priv);
> +       if (ret)
> +               return ret;
> +
> +       or->fb_id = r.fb_id;
> +
> +       return 0;
> +}
> +
> +static int format_check(const struct drm_mode_fb_cmd2 *r)
> +{
> +       uint32_t format = r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN;
> +
> +       switch (format) {
> +       case DRM_FORMAT_C8:
> +       case DRM_FORMAT_RGB332:
> +       case DRM_FORMAT_BGR233:
> +       case DRM_FORMAT_XRGB4444:
> +       case DRM_FORMAT_XBGR4444:
> +       case DRM_FORMAT_RGBX4444:
> +       case DRM_FORMAT_BGRX4444:
> +       case DRM_FORMAT_ARGB4444:
> +       case DRM_FORMAT_ABGR4444:
> +       case DRM_FORMAT_RGBA4444:
> +       case DRM_FORMAT_BGRA4444:
> +       case DRM_FORMAT_XRGB1555:
> +       case DRM_FORMAT_XBGR1555:
> +       case DRM_FORMAT_RGBX5551:
> +       case DRM_FORMAT_BGRX5551:
> +       case DRM_FORMAT_ARGB1555:
> +       case DRM_FORMAT_ABGR1555:
> +       case DRM_FORMAT_RGBA5551:
> +       case DRM_FORMAT_BGRA5551:
> +       case DRM_FORMAT_RGB565:
> +       case DRM_FORMAT_BGR565:
> +       case DRM_FORMAT_RGB888:
> +       case DRM_FORMAT_BGR888:
> +       case DRM_FORMAT_XRGB8888:
> +       case DRM_FORMAT_XBGR8888:
> +       case DRM_FORMAT_RGBX8888:
> +       case DRM_FORMAT_BGRX8888:
> +       case DRM_FORMAT_ARGB8888:
> +       case DRM_FORMAT_ABGR8888:
> +       case DRM_FORMAT_RGBA8888:
> +       case DRM_FORMAT_BGRA8888:
> +       case DRM_FORMAT_XRGB2101010:
> +       case DRM_FORMAT_XBGR2101010:
> +       case DRM_FORMAT_RGBX1010102:
> +       case DRM_FORMAT_BGRX1010102:
> +       case DRM_FORMAT_ARGB2101010:
> +       case DRM_FORMAT_ABGR2101010:
> +       case DRM_FORMAT_RGBA1010102:
> +       case DRM_FORMAT_BGRA1010102:
> +       case DRM_FORMAT_YUYV:
> +       case DRM_FORMAT_YVYU:
> +       case DRM_FORMAT_UYVY:
> +       case DRM_FORMAT_VYUY:
> +       case DRM_FORMAT_AYUV:
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_NV21:
> +       case DRM_FORMAT_NV16:
> +       case DRM_FORMAT_NV61:
> +       case DRM_FORMAT_NV24:
> +       case DRM_FORMAT_NV42:
> +       case DRM_FORMAT_YUV410:
> +       case DRM_FORMAT_YVU410:
> +       case DRM_FORMAT_YUV411:
> +       case DRM_FORMAT_YVU411:
> +       case DRM_FORMAT_YUV420:
> +       case DRM_FORMAT_YVU420:
> +       case DRM_FORMAT_YUV422:
> +       case DRM_FORMAT_YVU422:
> +       case DRM_FORMAT_YUV444:
> +       case DRM_FORMAT_YVU444:
> +               return 0;
> +       default:
> +               DRM_DEBUG_KMS("invalid pixel format %s\n",
> +                             drm_get_format_name(r->pixel_format));
> +               return -EINVAL;
> +       }
> +}
> +
> +static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
> +{
> +       int ret, hsub, vsub, num_planes, i;
> +
> +       ret = format_check(r);
> +       if (ret) {
> +               DRM_DEBUG_KMS("bad framebuffer format %s\n",
> +                             drm_get_format_name(r->pixel_format));
> +               return ret;
> +       }
> +
> +       hsub = drm_format_horz_chroma_subsampling(r->pixel_format);
> +       vsub = drm_format_vert_chroma_subsampling(r->pixel_format);
> +       num_planes = drm_format_num_planes(r->pixel_format);
> +
> +       if (r->width == 0 || r->width % hsub) {
> +               DRM_DEBUG_KMS("bad framebuffer width %u\n", r->width);
> +               return -EINVAL;
> +       }
> +
> +       if (r->height == 0 || r->height % vsub) {
> +               DRM_DEBUG_KMS("bad framebuffer height %u\n", r->height);
> +               return -EINVAL;
> +       }
> +
> +       for (i = 0; i < num_planes; i++) {
> +               unsigned int width = r->width / (i != 0 ? hsub : 1);
> +               unsigned int height = r->height / (i != 0 ? vsub : 1);
> +               unsigned int cpp = drm_format_plane_cpp(r->pixel_format, i);
> +
> +               if (!r->handles[i]) {
> +                       DRM_DEBUG_KMS("no buffer object handle for plane %d\n", i);
> +                       return -EINVAL;
> +               }
> +
> +               if ((uint64_t) width * cpp > UINT_MAX)
> +                       return -ERANGE;
> +
> +               if ((uint64_t) height * r->pitches[i] + r->offsets[i] > UINT_MAX)
> +                       return -ERANGE;
> +
> +               if (r->pitches[i] < width * cpp) {
> +                       DRM_DEBUG_KMS("bad pitch %u for plane %d\n", r->pitches[i], i);
> +                       return -EINVAL;
> +               }
> +
> +               if (r->modifier[i] && !(r->flags & DRM_MODE_FB_MODIFIERS)) {
> +                       DRM_DEBUG_KMS("bad fb modifier %llu for plane %d\n",
> +                                     r->modifier[i], i);
> +                       return -EINVAL;
> +               }
> +
> +               /* modifier specific checks: */
> +               switch (r->modifier[i]) {
> +               case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
> +                       /* NOTE: the pitch restriction may be lifted later if it turns
> +                        * out that no hw has this restriction:
> +                        */
> +                       if (r->pixel_format != DRM_FORMAT_NV12 ||
> +                                       width % 128 || height % 32 ||
> +                                       r->pitches[i] % 128) {
> +                               DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
> +                               return -EINVAL;
> +                       }
> +                       break;
> +
> +               default:
> +                       break;
> +               }
> +       }
> +
> +       for (i = num_planes; i < 4; i++) {
> +               if (r->modifier[i]) {
> +                       DRM_DEBUG_KMS("non-zero modifier for unused plane %d\n", i);
> +                       return -EINVAL;
> +               }
> +
> +               /* Pre-FB_MODIFIERS userspace didn't clear the structs properly. */
> +               if (!(r->flags & DRM_MODE_FB_MODIFIERS))
> +                       continue;
> +
> +               if (r->handles[i]) {
> +                       DRM_DEBUG_KMS("buffer object handle for unused plane %d\n", i);
> +                       return -EINVAL;
> +               }
> +
> +               if (r->pitches[i]) {
> +                       DRM_DEBUG_KMS("non-zero pitch for unused plane %d\n", i);
> +                       return -EINVAL;
> +               }
> +
> +               if (r->offsets[i]) {
> +                       DRM_DEBUG_KMS("non-zero offset for unused plane %d\n", i);
> +                       return -EINVAL;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +struct drm_framebuffer *
> +drm_internal_framebuffer_create(struct drm_device *dev,
> +                               const struct drm_mode_fb_cmd2 *r,
> +                               struct drm_file *file_priv)
> +{
> +       struct drm_mode_config *config = &dev->mode_config;
> +       struct drm_framebuffer *fb;
> +       int ret;
> +
> +       if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) {
> +               DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if ((config->min_width > r->width) || (r->width > config->max_width)) {
> +               DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= %d\n",
> +                         r->width, config->min_width, config->max_width);
> +               return ERR_PTR(-EINVAL);
> +       }
> +       if ((config->min_height > r->height) || (r->height > config->max_height)) {
> +               DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= %d\n",
> +                         r->height, config->min_height, config->max_height);
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       if (r->flags & DRM_MODE_FB_MODIFIERS &&
> +           !dev->mode_config.allow_fb_modifiers) {
> +               DRM_DEBUG_KMS("driver does not support fb modifiers\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       ret = framebuffer_check(r);
> +       if (ret)
> +               return ERR_PTR(ret);
> +
> +       fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
> +       if (IS_ERR(fb)) {
> +               DRM_DEBUG_KMS("could not create framebuffer\n");
> +               return fb;
> +       }
> +
> +       return fb;
> +}
> +
> +/**
> + * drm_mode_addfb2 - add an FB to the graphics configuration
> + * @dev: drm device for the ioctl
> + * @data: data pointer for the ioctl
> + * @file_priv: drm file for the ioctl call
> + *
> + * Add a new FB to the specified CRTC, given a user request with format. This is
> + * the 2nd version of the addfb ioctl, which supports multi-planar framebuffers
> + * and uses fourcc codes as pixel format specifiers.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_addfb2(struct drm_device *dev,
> +                   void *data, struct drm_file *file_priv)
> +{
> +       struct drm_mode_fb_cmd2 *r = data;
> +       struct drm_framebuffer *fb;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +               return -EINVAL;
> +
> +       fb = drm_internal_framebuffer_create(dev, r, file_priv);
> +       if (IS_ERR(fb))
> +               return PTR_ERR(fb);
> +
> +       DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
> +       r->fb_id = fb->base.id;
> +
> +       /* Transfer ownership to the filp for reaping on close */
> +       mutex_lock(&file_priv->fbs_lock);
> +       list_add(&fb->filp_head, &file_priv->fbs);
> +       mutex_unlock(&file_priv->fbs_lock);
> +
> +       return 0;
> +}
> +
> +struct drm_mode_rmfb_work {
> +       struct work_struct work;
> +       struct list_head fbs;
> +};
> +
> +static void drm_mode_rmfb_work_fn(struct work_struct *w)
> +{
> +       struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
> +
> +       while (!list_empty(&arg->fbs)) {
> +               struct drm_framebuffer *fb =
> +                       list_first_entry(&arg->fbs, typeof(*fb), filp_head);
> +
> +               list_del_init(&fb->filp_head);
> +               drm_framebuffer_remove(fb);
> +       }
> +}
> +
> +/**
> + * drm_mode_rmfb - remove an FB from the configuration
> + * @dev: drm device for the ioctl
> + * @data: data pointer for the ioctl
> + * @file_priv: drm file for the ioctl call
> + *
> + * Remove the FB specified by the user.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_rmfb(struct drm_device *dev,
> +                  void *data, struct drm_file *file_priv)
> +{
> +       struct drm_framebuffer *fb = NULL;
> +       struct drm_framebuffer *fbl = NULL;
> +       uint32_t *id = data;
> +       int found = 0;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +               return -EINVAL;
> +
> +       fb = drm_framebuffer_lookup(dev, *id);
> +       if (!fb)
> +               return -ENOENT;
> +
> +       mutex_lock(&file_priv->fbs_lock);
> +       list_for_each_entry(fbl, &file_priv->fbs, filp_head)
> +               if (fb == fbl)
> +                       found = 1;
> +       if (!found) {
> +               mutex_unlock(&file_priv->fbs_lock);
> +               goto fail_unref;
> +       }
> +
> +       list_del_init(&fb->filp_head);
> +       mutex_unlock(&file_priv->fbs_lock);
> +
> +       /* drop the reference we picked up in framebuffer lookup */
> +       drm_framebuffer_unreference(fb);
> +
> +       /*
> +        * we now own the reference that was stored in the fbs list
> +        *
> +        * drm_framebuffer_remove may fail with -EINTR on pending signals,
> +        * so run this in a separate stack as there's no way to correctly
> +        * handle this after the fb is already removed from the lookup table.
> +        */
> +       if (drm_framebuffer_read_refcount(fb) > 1) {
> +               struct drm_mode_rmfb_work arg;
> +
> +               INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
> +               INIT_LIST_HEAD(&arg.fbs);
> +               list_add_tail(&fb->filp_head, &arg.fbs);
> +
> +               schedule_work(&arg.work);
> +               flush_work(&arg.work);
> +               destroy_work_on_stack(&arg.work);
> +       } else
> +               drm_framebuffer_unreference(fb);
> +
> +       return 0;
> +
> +fail_unref:
> +       drm_framebuffer_unreference(fb);
> +       return -ENOENT;
> +}
> +
> +/**
> + * drm_mode_getfb - get FB info
> + * @dev: drm device for the ioctl
> + * @data: data pointer for the ioctl
> + * @file_priv: drm file for the ioctl call
> + *
> + * Lookup the FB given its ID and return info about it.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_getfb(struct drm_device *dev,
> +                  void *data, struct drm_file *file_priv)
> +{
> +       struct drm_mode_fb_cmd *r = data;
> +       struct drm_framebuffer *fb;
> +       int ret;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +               return -EINVAL;
> +
> +       fb = drm_framebuffer_lookup(dev, r->fb_id);
> +       if (!fb)
> +               return -ENOENT;
> +
> +       r->height = fb->height;
> +       r->width = fb->width;
> +       r->depth = fb->depth;
> +       r->bpp = fb->bits_per_pixel;
> +       r->pitch = fb->pitches[0];
> +       if (fb->funcs->create_handle) {
> +               if (drm_is_current_master(file_priv) || capable(CAP_SYS_ADMIN) ||
> +                   drm_is_control_client(file_priv)) {
> +                       ret = fb->funcs->create_handle(fb, file_priv,
> +                                                      &r->handle);
> +               } else {
> +                       /* GET_FB() is an unprivileged ioctl so we must not
> +                        * return a buffer-handle to non-master processes! For
> +                        * backwards-compatibility reasons, we cannot make
> +                        * GET_FB() privileged, so just return an invalid handle
> +                        * for non-masters. */
> +                       r->handle = 0;
> +                       ret = 0;
> +               }
> +       } else {
> +               ret = -ENODEV;
> +       }
> +
> +       drm_framebuffer_unreference(fb);
> +
> +       return ret;
> +}
> +
> +/**
> + * drm_mode_dirtyfb_ioctl - flush frontbuffer rendering on an FB
> + * @dev: drm device for the ioctl
> + * @data: data pointer for the ioctl
> + * @file_priv: drm file for the ioctl call
> + *
> + * Lookup the FB and flush out the damaged area supplied by userspace as a clip
> + * rectangle list. Generic userspace which does frontbuffer rendering must call
> + * this ioctl to flush out the changes on manual-update display outputs, e.g.
> + * usb display-link, mipi manual update panels or edp panel self refresh modes.
> + *
> + * Modesetting drivers which always update the frontbuffer do not need to
> + * implement the corresponding ->dirty framebuffer callback.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
> +                          void *data, struct drm_file *file_priv)
> +{
> +       struct drm_clip_rect __user *clips_ptr;
> +       struct drm_clip_rect *clips = NULL;
> +       struct drm_mode_fb_dirty_cmd *r = data;
> +       struct drm_framebuffer *fb;
> +       unsigned flags;
> +       int num_clips;
> +       int ret;
> +
> +       if (!drm_core_check_feature(dev, DRIVER_MODESET))
> +               return -EINVAL;
> +
> +       fb = drm_framebuffer_lookup(dev, r->fb_id);
> +       if (!fb)
> +               return -ENOENT;
> +
> +       num_clips = r->num_clips;
> +       clips_ptr = (struct drm_clip_rect __user *)(unsigned long)r->clips_ptr;
> +
> +       if (!num_clips != !clips_ptr) {
> +               ret = -EINVAL;
> +               goto out_err1;
> +       }
> +
> +       flags = DRM_MODE_FB_DIRTY_FLAGS & r->flags;
> +
> +       /* If userspace annotates copy, clips must come in pairs */
> +       if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY && (num_clips % 2)) {
> +               ret = -EINVAL;
> +               goto out_err1;
> +       }
> +
> +       if (num_clips && clips_ptr) {
> +               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
> +                       ret = -EINVAL;
> +                       goto out_err1;
> +               }
> +               clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL);
> +               if (!clips) {
> +                       ret = -ENOMEM;
> +                       goto out_err1;
> +               }
> +
> +               ret = copy_from_user(clips, clips_ptr,
> +                                    num_clips * sizeof(*clips));
> +               if (ret) {
> +                       ret = -EFAULT;
> +                       goto out_err2;
> +               }
> +       }
> +
> +       if (fb->funcs->dirty) {
> +               ret = fb->funcs->dirty(fb, file_priv, flags, r->color,
> +                                      clips, num_clips);
> +       } else {
> +               ret = -ENOSYS;
> +       }
> +
> +out_err2:
> +       kfree(clips);
> +out_err1:
> +       drm_framebuffer_unreference(fb);
> +
> +       return ret;
> +}
> +
> +/**
> + * drm_fb_release - remove and free the FBs on this file
> + * @priv: drm file for the ioctl
> + *
> + * Destroy all the FBs associated with @filp.
> + *
> + * Called by the user via ioctl.
> + *
> + * Returns:
> + * Zero on success, negative errno on failure.
> + */
> +void drm_fb_release(struct drm_file *priv)
> +{
> +       struct drm_framebuffer *fb, *tfb;
> +       struct drm_mode_rmfb_work arg;
> +
> +       INIT_LIST_HEAD(&arg.fbs);
> +
> +       /*
> +        * When the file gets released that means no one else can access the fb
> +        * list any more, so no need to grab fpriv->fbs_lock. And we need to
> +        * avoid upsetting lockdep since the universal cursor code adds a
> +        * framebuffer while holding mutex locks.
> +        *
> +        * Note that a real deadlock between fpriv->fbs_lock and the modeset
> +        * locks is impossible here since no one else but this function can get
> +        * at it any more.
> +        */
> +       list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
> +               if (drm_framebuffer_read_refcount(fb) > 1) {
> +                       list_move_tail(&fb->filp_head, &arg.fbs);
> +               } else {
> +                       list_del_init(&fb->filp_head);
> +
> +                       /* This drops the fpriv->fbs reference. */
> +                       drm_framebuffer_unreference(fb);
> +               }
> +       }
> +
> +       if (!list_empty(&arg.fbs)) {
> +               INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
> +
> +               schedule_work(&arg.work);
> +               flush_work(&arg.work);
> +               destroy_work_on_stack(&arg.work);
> +       }
> +}
> +
> +void drm_framebuffer_free(struct kref *kref)
> +{
> +       struct drm_framebuffer *fb =
> +                       container_of(kref, struct drm_framebuffer, base.refcount);
> +       struct drm_device *dev = fb->dev;
> +
> +       /*
> +        * The lookup idr holds a weak reference, which has not necessarily been
> +        * removed at this point. Check for that.
> +        */
> +       drm_mode_object_unregister(dev, &fb->base);
> +
> +       fb->funcs->destroy(fb);
> +}
> +
> +/**
> + * drm_framebuffer_init - initialize a framebuffer
> + * @dev: DRM device
> + * @fb: framebuffer to be initialized
> + * @funcs: ... with these functions
> + *
> + * Allocates an ID for the framebuffer's parent mode object, sets its mode
> + * functions & device file and adds it to the master fd list.
> + *
> + * IMPORTANT:
> + * This functions publishes the fb and makes it available for concurrent access
> + * by other users. Which means by this point the fb _must_ be fully set up -
> + * since all the fb attributes are invariant over its lifetime, no further
> + * locking but only correct reference counting is required.
> + *
> + * Returns:
> + * Zero on success, error code on failure.
> + */
> +int drm_framebuffer_init(struct drm_device *dev, struct drm_framebuffer *fb,
> +                        const struct drm_framebuffer_funcs *funcs)
> +{
> +       int ret;
> +
> +       INIT_LIST_HEAD(&fb->filp_head);
> +       fb->dev = dev;
> +       fb->funcs = funcs;
> +
> +       ret = drm_mode_object_get_reg(dev, &fb->base, DRM_MODE_OBJECT_FB,
> +                                     false, drm_framebuffer_free);
> +       if (ret)
> +               goto out;
> +
> +       mutex_lock(&dev->mode_config.fb_lock);
> +       dev->mode_config.num_fb++;
> +       list_add(&fb->head, &dev->mode_config.fb_list);
> +       mutex_unlock(&dev->mode_config.fb_lock);
> +
> +       drm_mode_object_register(dev, &fb->base);
> +out:
> +       return ret;
> +}
> +EXPORT_SYMBOL(drm_framebuffer_init);
> +
> +/**
> + * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference
> + * @dev: drm device
> + * @id: id of the fb object
> + *
> + * If successful, this grabs an additional reference to the framebuffer -
> + * callers need to make sure to eventually unreference the returned framebuffer
> + * again, using @drm_framebuffer_unreference.
> + */
> +struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
> +                                              uint32_t id)
> +{
> +       struct drm_mode_object *obj;
> +       struct drm_framebuffer *fb = NULL;
> +
> +       obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB);
> +       if (obj)
> +               fb = obj_to_fb(obj);
> +       return fb;
> +}
> +EXPORT_SYMBOL(drm_framebuffer_lookup);
> +
> +/**
> + * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
> + * @fb: fb to unregister
> + *
> + * Drivers need to call this when cleaning up driver-private framebuffers, e.g.
> + * those used for fbdev. Note that the caller must hold a reference of it's own,
> + * i.e. the object may not be destroyed through this call (since it'll lead to a
> + * locking inversion).
> + */
> +void drm_framebuffer_unregister_private(struct drm_framebuffer *fb)
> +{
> +       struct drm_device *dev;
> +
> +       if (!fb)
> +               return;
> +
> +       dev = fb->dev;
> +
> +       /* Mark fb as reaped and drop idr ref. */
> +       drm_mode_object_unregister(dev, &fb->base);
> +}
> +EXPORT_SYMBOL(drm_framebuffer_unregister_private);
> +
> +/**
> + * drm_framebuffer_cleanup - remove a framebuffer object
> + * @fb: framebuffer to remove
> + *
> + * Cleanup framebuffer. This function is intended to be used from the drivers
> + * ->destroy callback. It can also be used to clean up driver private
> + * framebuffers embedded into a larger structure.
> + *
> + * Note that this function does not remove the fb from active usuage - if it is
> + * still used anywhere, hilarity can ensue since userspace could call getfb on
> + * the id and get back -EINVAL. Obviously no concern at driver unload time.
> + *
> + * Also, the framebuffer will not be removed from the lookup idr - for
> + * user-created framebuffers this will happen in in the rmfb ioctl. For
> + * driver-private objects (e.g. for fbdev) drivers need to explicitly call
> + * drm_framebuffer_unregister_private.
> + */
> +void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
> +{
> +       struct drm_device *dev = fb->dev;
> +
> +       mutex_lock(&dev->mode_config.fb_lock);
> +       list_del(&fb->head);
> +       dev->mode_config.num_fb--;
> +       mutex_unlock(&dev->mode_config.fb_lock);
> +}
> +EXPORT_SYMBOL(drm_framebuffer_cleanup);
> +
> +/**
> + * drm_framebuffer_remove - remove and unreference a framebuffer object
> + * @fb: framebuffer to remove
> + *
> + * Scans all the CRTCs and planes in @dev's mode_config.  If they're
> + * using @fb, removes it, setting it to NULL. Then drops the reference to the
> + * passed-in framebuffer. Might take the modeset locks.
> + *
> + * Note that this function optimizes the cleanup away if the caller holds the
> + * last reference to the framebuffer. It is also guaranteed to not take the
> + * modeset locks in this case.
> + */
> +void drm_framebuffer_remove(struct drm_framebuffer *fb)
> +{
> +       struct drm_device *dev;
> +       struct drm_crtc *crtc;
> +       struct drm_plane *plane;
> +
> +       if (!fb)
> +               return;
> +
> +       dev = fb->dev;
> +
> +       WARN_ON(!list_empty(&fb->filp_head));
> +
> +       /*
> +        * drm ABI mandates that we remove any deleted framebuffers from active
> +        * useage. But since most sane clients only remove framebuffers they no
> +        * longer need, try to optimize this away.
> +        *
> +        * Since we're holding a reference ourselves, observing a refcount of 1
> +        * means that we're the last holder and can skip it. Also, the refcount
> +        * can never increase from 1 again, so we don't need any barriers or
> +        * locks.
> +        *
> +        * Note that userspace could try to race with use and instate a new
> +        * usage _after_ we've cleared all current ones. End result will be an
> +        * in-use fb with fb-id == 0. Userspace is allowed to shoot its own foot
> +        * in this manner.
> +        */
> +       if (drm_framebuffer_read_refcount(fb) > 1) {
> +               if (dev->mode_config.funcs->atomic_commit) {
> +                       drm_atomic_remove_fb(fb);
> +                       goto out;
> +               }
> +
> +               drm_modeset_lock_all(dev);
> +               /* remove from any CRTC */
> +               drm_for_each_crtc(crtc, dev) {
> +                       if (crtc->primary->fb == fb) {
> +                               /* should turn off the crtc */
> +                               if (drm_crtc_force_disable(crtc))
> +                                       DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
> +                       }
> +               }
> +
> +               drm_for_each_plane(plane, dev) {
> +                       if (plane->fb == fb)
> +                               drm_plane_force_disable(plane);
> +               }
> +               drm_modeset_unlock_all(dev);
> +       }
> +
> +out:
> +       drm_framebuffer_unreference(fb);
> +}
> +EXPORT_SYMBOL(drm_framebuffer_remove);
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 5a7809f029ba..0119161cad57 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -36,10 +36,12 @@
>  #include <uapi/drm/drm_fourcc.h>
>  #include <drm/drm_modeset_lock.h>
>  #include <drm/drm_rect.h>
> +#include <drm/drm_modeset.h>
> +#include <drm/drm_framebuffer.h>
> +#include <drm/drm_modes.h>
>
>  struct drm_device;
>  struct drm_mode_set;
> -struct drm_framebuffer;
>  struct drm_object_properties;
>  struct drm_file;
>  struct drm_clip_rect;
> @@ -47,14 +49,6 @@ struct device_node;
>  struct fence;
>  struct edid;
>
> -struct drm_mode_object {
> -       uint32_t id;
> -       uint32_t type;
> -       struct drm_object_properties *properties;
> -       struct kref refcount;
> -       void (*free_cb)(struct kref *kref);
> -};
> -
>  #define DRM_OBJECT_MAX_PROPERTY 24
>  struct drm_object_properties {
>         int count, atomic_count;
> @@ -94,15 +88,6 @@ static inline uint64_t I642U64(int64_t val)
>  #define DRM_REFLECT_Y  BIT(5)
>  #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
>
> -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 */
> -};
> -
> -#include <drm/drm_modes.h>
> -
>  enum drm_connector_status {
>         connector_status_connected = 1,
>         connector_status_disconnected = 2,
> @@ -166,101 +151,6 @@ struct drm_tile_group {
>         u8 group_data[8];
>  };
>
> -/**
> - * struct drm_framebuffer_funcs - framebuffer hooks
> - */
> -struct drm_framebuffer_funcs {
> -       /**
> -        * @destroy:
> -        *
> -        * Clean up framebuffer resources, specifically also unreference the
> -        * backing storage. The core guarantees to call this function for every
> -        * framebuffer successfully created by ->fb_create() in
> -        * &drm_mode_config_funcs. Drivers must also call
> -        * drm_framebuffer_cleanup() to release DRM core resources for this
> -        * framebuffer.
> -        */
> -       void (*destroy)(struct drm_framebuffer *framebuffer);
> -
> -       /**
> -        * @create_handle:
> -        *
> -        * Create a buffer handle in the driver-specific buffer manager (either
> -        * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
> -        * the core to implement the GETFB IOCTL, which returns (for
> -        * sufficiently priviledged user) also a native buffer handle. This can
> -        * be used for seamless transitions between modesetting clients by
> -        * copying the current screen contents to a private buffer and blending
> -        * between that and the new contents.
> -        *
> -        * GEM based drivers should call drm_gem_handle_create() to create the
> -        * handle.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 on success or a negative error code on failure.
> -        */
> -       int (*create_handle)(struct drm_framebuffer *fb,
> -                            struct drm_file *file_priv,
> -                            unsigned int *handle);
> -       /**
> -        * @dirty:
> -        *
> -        * Optional callback for the dirty fb IOCTL.
> -        *
> -        * Userspace can notify the driver via this callback that an area of the
> -        * framebuffer has changed and should be flushed to the display
> -        * hardware. This can also be used internally, e.g. by the fbdev
> -        * emulation, though that's not the case currently.
> -        *
> -        * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
> -        * for more information as all the semantics and arguments have a one to
> -        * one mapping on this function.
> -        *
> -        * RETURNS:
> -        *
> -        * 0 on success or a negative error code on failure.
> -        */
> -       int (*dirty)(struct drm_framebuffer *framebuffer,
> -                    struct drm_file *file_priv, unsigned flags,
> -                    unsigned color, struct drm_clip_rect *clips,
> -                    unsigned num_clips);
> -};
> -
> -struct drm_framebuffer {
> -       struct drm_device *dev;
> -       /*
> -        * Note that the fb is refcounted for the benefit of driver internals,
> -        * for example some hw, disabling a CRTC/plane is asynchronous, and
> -        * scanout does not actually complete until the next vblank.  So some
> -        * cleanup (like releasing the reference(s) on the backing GEM bo(s))
> -        * should be deferred.  In cases like this, the driver would like to
> -        * hold a ref to the fb even though it has already been removed from
> -        * userspace perspective.
> -        * The refcount is stored inside the mode object.
> -        */
> -       /*
> -        * Place on the dev->mode_config.fb_list, access protected by
> -        * dev->mode_config.fb_lock.
> -        */
> -       struct list_head head;
> -       struct drm_mode_object base;
> -       const struct drm_framebuffer_funcs *funcs;
> -       unsigned int pitches[4];
> -       unsigned int offsets[4];
> -       uint64_t modifier[4];
> -       unsigned int width;
> -       unsigned int height;
> -       /* depth can be 15 or 16 */
> -       unsigned int depth;
> -       int bits_per_pixel;
> -       int flags;
> -       uint32_t pixel_format; /* fourcc format */
> -       int hot_x;
> -       int hot_y;
> -       struct list_head filp_head;
> -};
> -
>  struct drm_property_blob {
>         struct drm_mode_object base;
>         struct drm_device *dev;
> @@ -2888,14 +2778,6 @@ extern int drm_object_property_set_value(struct drm_mode_object *obj,
>  extern int drm_object_property_get_value(struct drm_mode_object *obj,
>                                          struct drm_property *property,
>                                          uint64_t *value);
> -extern int drm_framebuffer_init(struct drm_device *dev,
> -                               struct drm_framebuffer *fb,
> -                               const struct drm_framebuffer_funcs *funcs);
> -extern struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
> -                                                     uint32_t id);
> -extern void drm_framebuffer_remove(struct drm_framebuffer *fb);
> -extern void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
> -extern void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
>
>  extern void drm_object_attach_property(struct drm_mode_object *obj,
>                                        struct drm_property *property,
> @@ -2976,11 +2858,6 @@ int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
>                                              unsigned int zpos);
>
>  /* Helpers */
> -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);
> -
>  static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
>                 uint32_t id)
>  {
> @@ -3049,39 +2926,6 @@ static inline uint32_t drm_color_lut_extract(uint32_t user_input,
>  }
>
>  /**
> - * drm_framebuffer_reference - incr the fb refcnt
> - * @fb: framebuffer
> - *
> - * This functions increments the fb's refcount.
> - */
> -static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
> -{
> -       drm_mode_object_reference(&fb->base);
> -}
> -
> -/**
> - * drm_framebuffer_unreference - unref a framebuffer
> - * @fb: framebuffer to unref
> - *
> - * This functions decrements the fb's refcount and frees it if it drops to zero.
> - */
> -static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
> -{
> -       drm_mode_object_unreference(&fb->base);
> -}
> -
> -/**
> - * drm_framebuffer_read_refcount - read the framebuffer reference count.
> - * @fb: framebuffer
> - *
> - * This functions returns the framebuffer's reference count.
> - */
> -static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
> -{
> -       return atomic_read(&fb->base.refcount.refcount);
> -}
> -
> -/**
>   * drm_connector_reference - incr the connector refcnt
>   * @connector: connector
>   *
> diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
> new file mode 100644
> index 000000000000..46abdace8fa5
> --- /dev/null
> +++ b/include/drm/drm_framebuffer.h
> @@ -0,0 +1,170 @@
> +/*
> + * 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_FRAMEBUFFER_H__
> +#define __DRM_FRAMEBUFFER_H__
> +
> +#include <linux/list.h>
> +#include <linux/ctype.h>
> +#include <drm/drm_modeset.h>
> +
> +struct drm_framebuffer;
> +struct drm_file;
> +struct drm_device;
> +
> +/**
> + * struct drm_framebuffer_funcs - framebuffer hooks
> + */
> +struct drm_framebuffer_funcs {
> +       /**
> +        * @destroy:
> +        *
> +        * Clean up framebuffer resources, specifically also unreference the
> +        * backing storage. The core guarantees to call this function for every
> +        * framebuffer successfully created by ->fb_create() in
> +        * &drm_mode_config_funcs. Drivers must also call
> +        * drm_framebuffer_cleanup() to release DRM core resources for this
> +        * framebuffer.
> +        */
> +       void (*destroy)(struct drm_framebuffer *framebuffer);
> +
> +       /**
> +        * @create_handle:
> +        *
> +        * Create a buffer handle in the driver-specific buffer manager (either
> +        * GEM or TTM) valid for the passed-in struct &drm_file. This is used by
> +        * the core to implement the GETFB IOCTL, which returns (for
> +        * sufficiently priviledged user) also a native buffer handle. This can
> +        * be used for seamless transitions between modesetting clients by
> +        * copying the current screen contents to a private buffer and blending
> +        * between that and the new contents.
> +        *
> +        * GEM based drivers should call drm_gem_handle_create() to create the
> +        * handle.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 on success or a negative error code on failure.
> +        */
> +       int (*create_handle)(struct drm_framebuffer *fb,
> +                            struct drm_file *file_priv,
> +                            unsigned int *handle);
> +       /**
> +        * @dirty:
> +        *
> +        * Optional callback for the dirty fb IOCTL.
> +        *
> +        * Userspace can notify the driver via this callback that an area of the
> +        * framebuffer has changed and should be flushed to the display
> +        * hardware. This can also be used internally, e.g. by the fbdev
> +        * emulation, though that's not the case currently.
> +        *
> +        * See documentation in drm_mode.h for the struct drm_mode_fb_dirty_cmd
> +        * for more information as all the semantics and arguments have a one to
> +        * one mapping on this function.
> +        *
> +        * RETURNS:
> +        *
> +        * 0 on success or a negative error code on failure.
> +        */
> +       int (*dirty)(struct drm_framebuffer *framebuffer,
> +                    struct drm_file *file_priv, unsigned flags,
> +                    unsigned color, struct drm_clip_rect *clips,
> +                    unsigned num_clips);
> +};
> +
> +struct drm_framebuffer {
> +       struct drm_device *dev;
> +       /*
> +        * Note that the fb is refcounted for the benefit of driver internals,
> +        * for example some hw, disabling a CRTC/plane is asynchronous, and
> +        * scanout does not actually complete until the next vblank.  So some
> +        * cleanup (like releasing the reference(s) on the backing GEM bo(s))
> +        * should be deferred.  In cases like this, the driver would like to
> +        * hold a ref to the fb even though it has already been removed from
> +        * userspace perspective.
> +        * The refcount is stored inside the mode object.
> +        */
> +       /*
> +        * Place on the dev->mode_config.fb_list, access protected by
> +        * dev->mode_config.fb_lock.
> +        */
> +       struct list_head head;
> +       struct drm_mode_object base;
> +       const struct drm_framebuffer_funcs *funcs;
> +       unsigned int pitches[4];
> +       unsigned int offsets[4];
> +       uint64_t modifier[4];
> +       unsigned int width;
> +       unsigned int height;
> +       /* depth can be 15 or 16 */
> +       unsigned int depth;
> +       int bits_per_pixel;
> +       int flags;
> +       uint32_t pixel_format; /* fourcc format */
> +       int hot_x;
> +       int hot_y;
> +       struct list_head filp_head;
> +};
> +
> +int drm_framebuffer_init(struct drm_device *dev,
> +                        struct drm_framebuffer *fb,
> +                        const struct drm_framebuffer_funcs *funcs);
> +struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
> +                                              uint32_t id);
> +void drm_framebuffer_remove(struct drm_framebuffer *fb);
> +void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
> +void drm_framebuffer_unregister_private(struct drm_framebuffer *fb);
> +
> +/**
> + * drm_framebuffer_reference - incr the fb refcnt
> + * @fb: framebuffer
> + *
> + * This functions increments the fb's refcount.
> + */
> +static inline void drm_framebuffer_reference(struct drm_framebuffer *fb)
> +{
> +       drm_mode_object_reference(&fb->base);
> +}
> +
> +/**
> + * drm_framebuffer_unreference - unref a framebuffer
> + * @fb: framebuffer to unref
> + *
> + * This functions decrements the fb's refcount and frees it if it drops to zero.
> + */
> +static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb)
> +{
> +       drm_mode_object_unreference(&fb->base);
> +}
> +
> +/**
> + * drm_framebuffer_read_refcount - read the framebuffer reference count.
> + * @fb: framebuffer
> + *
> + * This functions returns the framebuffer's reference count.
> + */
> +static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
> +{
> +       return atomic_read(&fb->base.refcount.refcount);
> +}
> +#endif
> diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h
> index 48e1a56ea283..fed9fe81590c 100644
> --- a/include/drm/drm_modes.h
> +++ b/include/drm/drm_modes.h
> @@ -27,6 +27,8 @@
>  #ifndef __DRM_MODES_H__
>  #define __DRM_MODES_H__
>
> +#include <drm/drm_modeset.h>
> +
>  /*
>   * Note on terminology:  here, for brevity and convenience, we refer to connector
>   * control chips as 'CRTCs'.  They can control any type of connector, VGA, LVDS,
> diff --git a/include/drm/drm_modeset.h b/include/drm/drm_modeset.h
> new file mode 100644
> index 000000000000..0c2b0f3c5f34
> --- /dev/null
> +++ b/include/drm/drm_modeset.h
> @@ -0,0 +1,50 @@
> +/*
> + * 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_MODESET_H__
> +#define __DRM_MODESET_H__
> +
> +#include <linux/kref.h>
> +struct drm_object_properties;
> +
> +struct drm_mode_object {
> +       uint32_t id;
> +       uint32_t type;
> +       struct drm_object_properties *properties;
> +       struct kref refcount;
> +       void (*free_cb)(struct kref *kref);
> +};
> +
> +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
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 14/21] drm: Extract drm_connector.[hc]
  2016-08-12 20:48 ` [PATCH 14/21] drm: Extract drm_connector.[hc] Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  2016-09-21 14:29   ` Sean Paul
  1 sibling, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, 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.
>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  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
> + * 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;
> +       }
> +
> +       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);
> +
> +       /* 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 1f79f629de52..07eba82a9998 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.
> @@ -580,20 +419,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
> @@ -628,312 +453,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;
> @@ -1337,39 +856,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,
> @@ -1490,225 +981,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
> @@ -1890,32 +1162,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;
> @@ -1950,133 +1201,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;
> @@ -3954,113 +3078,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
> @@ -4137,54 +3154,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)
> @@ -4266,7 +3235,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);
> @@ -4278,22 +3247,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)
>  {
> @@ -4359,47 +3312,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 f4d041800551..e30ea0be6417 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -39,31 +39,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);
> @@ -88,61 +73,6 @@ static inline uint64_t I642U64(int64_t val)
>  #define DRM_REFLECT_Y  BIT(5)
>  #define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
>
> -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;
> @@ -179,7 +109,6 @@ struct drm_property {
>  };
>
>  struct drm_crtc;
> -struct drm_connector;
>  struct drm_encoder;
>  struct drm_pending_vblank_event;
>  struct drm_plane;
> @@ -188,7 +117,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;
>
>  /**
> @@ -734,291 +662,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.
> @@ -1069,8 +712,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
> @@ -1111,171 +752,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
> @@ -2615,7 +2091,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)
> @@ -2661,19 +2136,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,
> @@ -2742,23 +2204,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);
> @@ -2819,16 +2268,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);
>
> @@ -2888,22 +2327,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)
>  {
> @@ -2931,28 +2354,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
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc
  2016-08-12 20:48 ` [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: DRI Development, Jonathan Corbet, linux-doc, Daniel Vetter

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> Move the documentation into Documentation/gpu, link it up and pull in
> the kernel doc.
>
> No actual text changes except that I did polish the kerneldoc a bit,
> especially for vga_client_register().
>
> v2: Remove some rst from vga-switcheroo.rst that I don't understand,
> but which seems to be the reason why the new vgaarbiter.rst sometimes
> drops out of the sidebar index.
>
> v3: Drop one level of headings and clarify the vgaarb one a bit.
>
> v4: Fix some typos (Sean).
>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: linux-doc@vger.kernel.org
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/index.rst          |   1 +
>  Documentation/gpu/vga-switcheroo.rst |   2 -
>  Documentation/gpu/vgaarbiter.rst     | 191 ++++++++++++++++++++++++++++++++++
>  Documentation/vgaarbiter.txt         | 192 -----------------------------------
>  drivers/gpu/vga/vgaarb.c             | 110 +++++++++++++++++++-
>  include/linux/vgaarb.h               | 128 +++--------------------
>  6 files changed, 316 insertions(+), 308 deletions(-)
>  create mode 100644 Documentation/gpu/vgaarbiter.rst
>  delete mode 100644 Documentation/vgaarbiter.txt
>
> diff --git a/Documentation/gpu/index.rst b/Documentation/gpu/index.rst
> index fcac0fa72056..ba92f45abb76 100644
> --- a/Documentation/gpu/index.rst
> +++ b/Documentation/gpu/index.rst
> @@ -12,3 +12,4 @@ Linux GPU Driver Developer's Guide
>     drm-uapi
>     i915
>     vga-switcheroo
> +   vgaarbiter
> diff --git a/Documentation/gpu/vga-switcheroo.rst b/Documentation/gpu/vga-switcheroo.rst
> index cbbdb994f1dd..463a74fc40d1 100644
> --- a/Documentation/gpu/vga-switcheroo.rst
> +++ b/Documentation/gpu/vga-switcheroo.rst
> @@ -1,5 +1,3 @@
> -.. _vga_switcheroo:
> -
>  ==============
>  VGA Switcheroo
>  ==============
> diff --git a/Documentation/gpu/vgaarbiter.rst b/Documentation/gpu/vgaarbiter.rst
> new file mode 100644
> index 000000000000..0b41b051d021
> --- /dev/null
> +++ b/Documentation/gpu/vgaarbiter.rst
> @@ -0,0 +1,191 @@
> +===========
> +VGA Arbiter
> +===========
> +
> +Graphic devices are accessed through ranges in I/O or memory space. While most
> +modern devices allow relocation of such ranges, some "Legacy" VGA devices
> +implemented on PCI will typically have the same "hard-decoded" addresses as
> +they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
> +Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
> +Section 7, Legacy Devices.
> +
> +The Resource Access Control (RAC) module inside the X server [0] existed for
> +the legacy VGA arbitration task (besides other bus management tasks) when more
> +than one legacy device co-exists on the same machine. But the problem happens
> +when these devices are trying to be accessed by different userspace clients
> +(e.g. two server in parallel). Their address assignments conflict. Moreover,
> +ideally, being a userspace application, it is not the role of the X server to
> +control bus resources. Therefore an arbitration scheme outside of the X server
> +is needed to control the sharing of these resources. This document introduces
> +the operation of the VGA arbiter implemented for the Linux kernel.
> +
> +vgaarb kernel/userspace ABI
> +---------------------------
> +
> +The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
> +scans all PCI devices and adds the VGA ones inside the arbitration. The
> +arbiter then enables/disables the decoding on different devices of the VGA
> +legacy instructions. Devices which do not want/need to use the arbiter may
> +explicitly tell it by calling vga_set_legacy_decoding().
> +
> +The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
> +which has the following semantics:
> +
> +open
> +        Opens a user instance of the arbiter. By default, it's attached to the
> +        default VGA device of the system.
> +
> +close
> +        Close a user instance. Release locks made by the user
> +
> +read
> +        Return a string indicating the status of the target like:
> +
> +        "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
> +
> +        An IO state string is of the form {io,mem,io+mem,none}, mc and
> +        ic are respectively mem and io lock counts (for debugging/
> +        diagnostic only). "decodes" indicate what the card currently
> +        decodes, "owns" indicates what is currently enabled on it, and
> +        "locks" indicates what is locked by this card. If the card is
> +        unplugged, we get "invalid" then for card_ID and an -ENODEV
> +        error is returned for any command until a new card is targeted.
> +
> +
> +write
> +        Write a command to the arbiter. List of commands:
> +
> +        target <card_ID>
> +                switch target to card <card_ID> (see below)
> +        lock <io_state>
> +                acquires locks on target ("none" is an invalid io_state)
> +        trylock <io_state>
> +                non-blocking acquire locks on target (returns EBUSY if
> +                unsuccessful)
> +        unlock <io_state>
> +                release locks on target
> +        unlock all
> +                release all locks on target held by this user (not implemented
> +                yet)
> +        decodes <io_state>
> +                set the legacy decoding attributes for the card
> +
> +        poll
> +                event if something changes on any card (not just the target)
> +
> +        card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
> +        to go back to the system default card (TODO: not implemented yet). Currently,
> +        only PCI is supported as a prefix, but the userland API may support other bus
> +        types in the future, even if the current kernel implementation doesn't.
> +
> +Note about locks:
> +
> +The driver keeps track of which user has which locks on which card. It
> +supports stacking, like the kernel one. This complexifies the implementation
> +a bit, but makes the arbiter more tolerant to user space problems and able
> +to properly cleanup in all cases when a process dies.
> +Currently, a max of 16 cards can have locks simultaneously issued from
> +user space for a given user (file descriptor instance) of the arbiter.
> +
> +In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
> +notify them being added/removed in the system and automatically added/removed
> +in the arbiter.
> +
> +There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
> +drivers want to use it.
> +
> +In-kernel interface
> +-------------------
> +
> +.. kernel-doc:: include/linux/vgaarb.h
> +   :internal:
> +
> +.. kernel-doc:: drivers/gpu/vga/vgaarb.c
> +   :export:
> +
> +libpciaccess
> +------------
> +
> +To use the vga arbiter char device it was implemented an API inside the
> +libpciaccess library. One field was added to struct pci_device (each device
> +on the system)::
> +
> +    /* the type of resource decoded by the device */
> +    int vgaarb_rsrc;
> +
> +Besides it, in pci_system were added::
> +
> +    int vgaarb_fd;
> +    int vga_count;
> +    struct pci_device *vga_target;
> +    struct pci_device *vga_default_dev;
> +
> +The vga_count is used to track how many cards are being arbitrated, so for
> +instance, if there is only one card, then it can completely escape arbitration.
> +
> +These functions below acquire VGA resources for the given card and mark those
> +resources as locked. If the resources requested are "normal" (and not legacy)
> +resources, the arbiter will first check whether the card is doing legacy
> +decoding for that type of resource. If yes, the lock is "converted" into a
> +legacy resource lock. The arbiter will first look for all VGA cards that
> +might conflict and disable their IOs and/or Memory access, including VGA
> +forwarding on P2P bridges if necessary, so that the requested resources can
> +be used. Then, the card is marked as locking these resources and the IO and/or
> +Memory access is enabled on the card (including VGA forwarding on parent
> +P2P bridges if any). In the case of vga_arb_lock(), the function will block
> +if some conflicting card is already locking one of the required resources (or
> +any resource on a different bus segment, since P2P bridges don't differentiate
> +VGA memory and IO afaik). If the card already owns the resources, the function
> +succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
> +calls are supported (a per-resource counter is maintained).
> +
> +Set the target device of this client. ::
> +
> +    int  pci_device_vgaarb_set_target   (struct pci_device *dev);
> +
> +For instance, in x86 if two devices on the same bus want to lock different
> +resources, both will succeed (lock). If devices are in different buses and
> +trying to lock different resources, only the first who tried succeeds. ::
> +
> +    int  pci_device_vgaarb_lock         (void);
> +    int  pci_device_vgaarb_trylock      (void);
> +
> +Unlock resources of device. ::
> +
> +    int  pci_device_vgaarb_unlock       (void);
> +
> +Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
> +Memory, both, or none. All cards default to both, the card driver (fbdev for
> +example) should tell the arbiter if it has disabled legacy decoding, so the
> +card can be left out of the arbitration process (and can be safe to take
> +interrupts at any time. ::
> +
> +    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);
> +
> +Connects to the arbiter device, allocates the struct ::
> +
> +    int  pci_device_vgaarb_init         (void);
> +
> +Close the connection ::
> +
> +    void pci_device_vgaarb_fini         (void);
> +
> +xf86VGAArbiter (X server implementation)
> +----------------------------------------
> +
> +X server basically wraps all the functions that touch VGA registers somehow.
> +
> +References
> +----------
> +
> +Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
> +with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
> +Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
> +enhancing the kernel code to adapt as a kernel module and also did the
> +implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
> +Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
> +
> +0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
> +1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
> +2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
> +3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
> diff --git a/Documentation/vgaarbiter.txt b/Documentation/vgaarbiter.txt
> deleted file mode 100644
> index 014423e2824c..000000000000
> --- a/Documentation/vgaarbiter.txt
> +++ /dev/null
> @@ -1,192 +0,0 @@
> -
> -VGA Arbiter
> -===========
> -
> -Graphic devices are accessed through ranges in I/O or memory space. While most
> -modern devices allow relocation of such ranges, some "Legacy" VGA devices
> -implemented on PCI will typically have the same "hard-decoded" addresses as
> -they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
> -Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
> -Section 7, Legacy Devices.
> -
> -The Resource Access Control (RAC) module inside the X server [0] existed for
> -the legacy VGA arbitration task (besides other bus management tasks) when more
> -than one legacy device co-exists on the same machine. But the problem happens
> -when these devices are trying to be accessed by different userspace clients
> -(e.g. two server in parallel). Their address assignments conflict. Moreover,
> -ideally, being a userspace application, it is not the role of the X server to
> -control bus resources. Therefore an arbitration scheme outside of the X server
> -is needed to control the sharing of these resources. This document introduces
> -the operation of the VGA arbiter implemented for the Linux kernel.
> -
> -----------------------------------------------------------------------------
> -
> -I.  Details and Theory of Operation
> -        I.1 vgaarb
> -        I.2 libpciaccess
> -        I.3 xf86VGAArbiter (X server implementation)
> -II. Credits
> -III.References
> -
> -
> -I. Details and Theory of Operation
> -==================================
> -
> -I.1 vgaarb
> -----------
> -
> -The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
> -scans all PCI devices and adds the VGA ones inside the arbitration. The
> -arbiter then enables/disables the decoding on different devices of the VGA
> -legacy instructions. Devices which do not want/need to use the arbiter may
> -explicitly tell it by calling vga_set_legacy_decoding().
> -
> -The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
> -which has the following semantics:
> -
> - open       : open user instance of the arbiter. By default, it's attached to
> -              the default VGA device of the system.
> -
> - close      : close user instance. Release locks made by the user
> -
> - read       : return a string indicating the status of the target like:
> -
> -              "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
> -
> -              An IO state string is of the form {io,mem,io+mem,none}, mc and
> -              ic are respectively mem and io lock counts (for debugging/
> -              diagnostic only). "decodes" indicate what the card currently
> -              decodes, "owns" indicates what is currently enabled on it, and
> -              "locks" indicates what is locked by this card. If the card is
> -              unplugged, we get "invalid" then for card_ID and an -ENODEV
> -              error is returned for any command until a new card is targeted.
> -
> -
> - write       : write a command to the arbiter. List of commands:
> -
> -  target <card_ID>   : switch target to card <card_ID> (see below)
> -  lock <io_state>    : acquires locks on target ("none" is an invalid io_state)
> -  trylock <io_state> : non-blocking acquire locks on target (returns EBUSY if
> -                       unsuccessful)
> -  unlock <io_state>  : release locks on target
> -  unlock all         : release all locks on target held by this user (not
> -                       implemented yet)
> -  decodes <io_state> : set the legacy decoding attributes for the card
> -
> -  poll               : event if something changes on any card (not just the
> -                       target)
> -
> -  card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
> -  to go back to the system default card (TODO: not implemented yet). Currently,
> -  only PCI is supported as a prefix, but the userland API may support other bus
> -  types in the future, even if the current kernel implementation doesn't.
> -
> -Note about locks:
> -
> -The driver keeps track of which user has which locks on which card. It
> -supports stacking, like the kernel one. This complexifies the implementation
> -a bit, but makes the arbiter more tolerant to user space problems and able
> -to properly cleanup in all cases when a process dies.
> -Currently, a max of 16 cards can have locks simultaneously issued from
> -user space for a given user (file descriptor instance) of the arbiter.
> -
> -In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
> -notify them being added/removed in the system and automatically added/removed
> -in the arbiter.
> -
> -There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
> -drivers want to use it.
> -
> -
> -I.2 libpciaccess
> -----------------
> -
> -To use the vga arbiter char device it was implemented an API inside the
> -libpciaccess library. One field was added to struct pci_device (each device
> -on the system):
> -
> -    /* the type of resource decoded by the device */
> -    int vgaarb_rsrc;
> -
> -Besides it, in pci_system were added:
> -
> -    int vgaarb_fd;
> -    int vga_count;
> -    struct pci_device *vga_target;
> -    struct pci_device *vga_default_dev;
> -
> -
> -The vga_count is used to track how many cards are being arbitrated, so for
> -instance, if there is only one card, then it can completely escape arbitration.
> -
> -
> -These functions below acquire VGA resources for the given card and mark those
> -resources as locked. If the resources requested are "normal" (and not legacy)
> -resources, the arbiter will first check whether the card is doing legacy
> -decoding for that type of resource. If yes, the lock is "converted" into a
> -legacy resource lock. The arbiter will first look for all VGA cards that
> -might conflict and disable their IOs and/or Memory access, including VGA
> -forwarding on P2P bridges if necessary, so that the requested resources can
> -be used. Then, the card is marked as locking these resources and the IO and/or
> -Memory access is enabled on the card (including VGA forwarding on parent
> -P2P bridges if any). In the case of vga_arb_lock(), the function will block
> -if some conflicting card is already locking one of the required resources (or
> -any resource on a different bus segment, since P2P bridges don't differentiate
> -VGA memory and IO afaik). If the card already owns the resources, the function
> -succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
> -calls are supported (a per-resource counter is maintained).
> -
> -
> -Set the target device of this client.
> -    int  pci_device_vgaarb_set_target   (struct pci_device *dev);
> -
> -
> -For instance, in x86 if two devices on the same bus want to lock different
> -resources, both will succeed (lock). If devices are in different buses and
> -trying to lock different resources, only the first who tried succeeds.
> -    int  pci_device_vgaarb_lock         (void);
> -    int  pci_device_vgaarb_trylock      (void);
> -
> -Unlock resources of device.
> -    int  pci_device_vgaarb_unlock       (void);
> -
> -Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
> -Memory, both, or none. All cards default to both, the card driver (fbdev for
> -example) should tell the arbiter if it has disabled legacy decoding, so the
> -card can be left out of the arbitration process (and can be safe to take
> -interrupts at any time.
> -    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);
> -
> -Connects to the arbiter device, allocates the struct
> -    int  pci_device_vgaarb_init         (void);
> -
> -Close the connection
> -    void pci_device_vgaarb_fini         (void);
> -
> -
> -I.3 xf86VGAArbiter (X server implementation)
> ---------------------------------------------
> -
> -(TODO)
> -
> -X server basically wraps all the functions that touch VGA registers somehow.
> -
> -
> -II. Credits
> -===========
> -
> -Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
> -with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
> -Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
> -enhancing the kernel code to adapt as a kernel module and also did the
> -implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
> -Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
> -
> -
> -III. References
> -==============
> -
> -[0] http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
> -[1] http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
> -[2] http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
> -[3] http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
> diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
> index f17cb0431833..1887f199ccb7 100644
> --- a/drivers/gpu/vga/vgaarb.c
> +++ b/drivers/gpu/vga/vgaarb.c
> @@ -131,7 +131,24 @@ static struct vga_device *vgadev_find(struct pci_dev *pdev)
>         return NULL;
>  }
>
> -/* Returns the default VGA device (vgacon's babe) */
> +/**
> + * vga_default_device - return the default VGA device, for vgacon
> + *
> + * This can be defined by the platform. The default implementation
> + * is rather dumb and will probably only work properly on single
> + * vga card setups and/or x86 platforms.
> + *
> + * If your VGA default device is not PCI, you'll have to return
> + * NULL here. In this case, I assume it will not conflict with
> + * any PCI card. If this is not true, I'll have to define two archs
> + * hooks for enabling/disabling the VGA default device if that is
> + * possible. This may be a problem with real _ISA_ VGA cards, in
> + * addition to a PCI one. I don't know at this point how to deal
> + * with that card. Can theirs IOs be disabled at all ? If not, then
> + * I suppose it's a matter of having the proper arch hook telling
> + * us about it, so we basically never allow anybody to succeed a
> + * vga_get()...
> + */
>  struct pci_dev *vga_default_device(void)
>  {
>         return vga_default;
> @@ -356,6 +373,40 @@ static void __vga_put(struct vga_device *vgadev, unsigned int rsrc)
>                 wake_up_all(&vga_wait_queue);
>  }
>
> +/**
> + * vga_get - acquire & locks VGA resources
> + * @pdev: pci device of the VGA card or NULL for the system default
> + * @rsrc: bit mask of resources to acquire and lock
> + * @interruptible: blocking should be interruptible by signals ?
> + *
> + * This function acquires VGA resources for the given card and mark those
> + * resources locked. If the resource requested are "normal" (and not legacy)
> + * resources, the arbiter will first check whether the card is doing legacy
> + * decoding for that type of resource. If yes, the lock is "converted" into a
> + * legacy resource lock.
> + *
> + * The arbiter will first look for all VGA cards that might conflict and disable
> + * their IOs and/or Memory access, including VGA forwarding on P2P bridges if
> + * necessary, so that the requested resources can be used. Then, the card is
> + * marked as locking these resources and the IO and/or Memory accesses are
> + * enabled on the card (including VGA forwarding on parent P2P bridges if any).
> + *
> + * This function will block if some conflicting card is already locking one of
> + * the required resources (or any resource on a different bus segment, since P2P
> + * bridges don't differentiate VGA memory and IO afaik). You can indicate
> + * whether this blocking should be interruptible by a signal (for userland
> + * interface) or not.
> + *
> + * Must not be called at interrupt time or in atomic context.  If the card
> + * already owns the resources, the function succeeds.  Nested calls are
> + * supported (a per-resource counter is maintained)
> + *
> + * On success, release the VGA resource again with vga_put().
> + *
> + * Returns:
> + *
> + * 0 on success, negative error code on failure.
> + */
>  int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
>  {
>         struct vga_device *vgadev, *conflict;
> @@ -408,6 +459,21 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
>  }
>  EXPORT_SYMBOL(vga_get);
>
> +/**
> + * vga_tryget - try to acquire & lock legacy VGA resources
> + * @pdev: pci devivce of VGA card or NULL for system default
> + * @rsrc: bit mask of resources to acquire and lock
> + *
> + * This function performs the same operation as vga_get(), but will return an
> + * error (-EBUSY) instead of blocking if the resources are already locked by
> + * another card. It can be called in any context
> + *
> + * On success, release the VGA resource again with vga_put().
> + *
> + * Returns:
> + *
> + * 0 on success, negative error code on failure.
> + */
>  int vga_tryget(struct pci_dev *pdev, unsigned int rsrc)
>  {
>         struct vga_device *vgadev;
> @@ -435,6 +501,16 @@ bail:
>  }
>  EXPORT_SYMBOL(vga_tryget);
>
> +/**
> + * vga_put - release lock on legacy VGA resources
> + * @pdev: pci device of VGA card or NULL for system default
> + * @rsrc: but mask of resource to release
> + *
> + * This fuction releases resources previously locked by vga_get() or
> + * vga_tryget(). The resources aren't disabled right away, so that a subsequence
> + * vga_get() on the same card will succeed immediately. Resources have a
> + * counter, so locks are only released if the counter reaches 0.
> + */
>  void vga_put(struct pci_dev *pdev, unsigned int rsrc)
>  {
>         struct vga_device *vgadev;
> @@ -716,7 +792,37 @@ void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes)
>  }
>  EXPORT_SYMBOL(vga_set_legacy_decoding);
>
> -/* call with NULL to unregister */
> +/**
> + * vga_client_register - register or unregister a VGA arbitration client
> + * @pdev: pci device of the VGA client
> + * @cookie: client cookie to be used in callbacks
> + * @irq_set_state: irq state change callback
> + * @set_vga_decode: vga decode change callback
> + *
> + * Clients have two callback mechanisms they can use.
> + *
> + * @irq_set_state callback: If a client can't disable its GPUs VGA
> + * resources, then we need to be able to ask it to turn off its irqs when we
> + * turn off its mem and io decoding.
> + *
> + * @set_vga_decode callback: If a client can disable its GPU VGA resource, it
> + * will get a callback from this to set the encode/decode state.
> + *
> + * Rationale: we cannot disable VGA decode resources unconditionally some single
> + * GPU laptops seem to require ACPI or BIOS access to the VGA registers to
> + * control things like backlights etc.  Hopefully newer multi-GPU laptops do
> + * something saner, and desktops won't have any special ACPI for this. The
> + * driver will get a callback when VGA arbitration is first used by userspace
> + * since some older X servers have issues.
> + *
> + * This function does not check whether a client for @pdev has been registered
> + * already.
> + *
> + * To unregister just call this function with @irq_set_state and @set_vga_decode
> + * both set to NULL for the same @pdev as originally used to register them.
> + *
> + * Returns: 0 on success, -1 on failure
> + */
>  int vga_client_register(struct pci_dev *pdev, void *cookie,
>                         void (*irq_set_state)(void *cookie, bool state),
>                         unsigned int (*set_vga_decode)(void *cookie,
> diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h
> index 8c3b412d84df..ee162e3e879b 100644
> --- a/include/linux/vgaarb.h
> +++ b/include/linux/vgaarb.h
> @@ -73,34 +73,6 @@ static inline void vga_set_legacy_decoding(struct pci_dev *pdev,
>                                            unsigned int decodes) { };
>  #endif
>
> -/**
> - *     vga_get         - acquire & locks VGA resources
> - *
> - *     @pdev: pci device of the VGA card or NULL for the system default
> - *     @rsrc: bit mask of resources to acquire and lock
> - *     @interruptible: blocking should be interruptible by signals ?
> - *
> - *     This function acquires VGA resources for the given
> - *     card and mark those resources locked. If the resource requested
> - *     are "normal" (and not legacy) resources, the arbiter will first check
> - *     whether the card is doing legacy decoding for that type of resource. If
> - *     yes, the lock is "converted" into a legacy resource lock.
> - *     The arbiter will first look for all VGA cards that might conflict
> - *     and disable their IOs and/or Memory access, including VGA forwarding
> - *     on P2P bridges if necessary, so that the requested resources can
> - *     be used. Then, the card is marked as locking these resources and
> - *     the IO and/or Memory accesse are enabled on the card (including
> - *     VGA forwarding on parent P2P bridges if any).
> - *     This function will block if some conflicting card is already locking
> - *     one of the required resources (or any resource on a different bus
> - *     segment, since P2P bridges don't differenciate VGA memory and IO
> - *     afaik). You can indicate whether this blocking should be interruptible
> - *     by a signal (for userland interface) or not.
> - *     Must not be called at interrupt time or in atomic context.
> - *     If the card already owns the resources, the function succeeds.
> - *     Nested calls are supported (a per-resource counter is maintained)
> - */
> -
>  #if defined(CONFIG_VGA_ARB)
>  extern int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible);
>  #else
> @@ -108,11 +80,14 @@ static inline int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interrupt
>  #endif
>
>  /**
> - *     vga_get_interruptible
> + * vga_get_interruptible
> + * @pdev: pci device of the VGA card or NULL for the system default
> + * @rsrc: bit mask of resources to acquire and lock
>   *
> - *     Shortcut to vga_get
> + * Shortcut to vga_get with interruptible set to true.
> + *
> + * On success, release the VGA resource again with vga_put().
>   */
> -
>  static inline int vga_get_interruptible(struct pci_dev *pdev,
>                                         unsigned int rsrc)
>  {
> @@ -120,47 +95,26 @@ static inline int vga_get_interruptible(struct pci_dev *pdev,
>  }
>
>  /**
> - *     vga_get_uninterruptible
> + * vga_get_uninterruptible - shortcut to vga_get()
> + * @pdev: pci device of the VGA card or NULL for the system default
> + * @rsrc: bit mask of resources to acquire and lock
>   *
> - *     Shortcut to vga_get
> + * Shortcut to vga_get with interruptible set to false.
> + *
> + * On success, release the VGA resource again with vga_put().
>   */
> -
>  static inline int vga_get_uninterruptible(struct pci_dev *pdev,
>                                           unsigned int rsrc)
>  {
>         return vga_get(pdev, rsrc, 0);
>  }
>
> -/**
> - *     vga_tryget      - try to acquire & lock legacy VGA resources
> - *
> - *     @pdev: pci devivce of VGA card or NULL for system default
> - *     @rsrc: bit mask of resources to acquire and lock
> - *
> - *     This function performs the same operation as vga_get(), but
> - *     will return an error (-EBUSY) instead of blocking if the resources
> - *     are already locked by another card. It can be called in any context
> - */
> -
>  #if defined(CONFIG_VGA_ARB)
>  extern int vga_tryget(struct pci_dev *pdev, unsigned int rsrc);
>  #else
>  static inline int vga_tryget(struct pci_dev *pdev, unsigned int rsrc) { return 0; }
>  #endif
>
> -/**
> - *     vga_put         - release lock on legacy VGA resources
> - *
> - *     @pdev: pci device of VGA card or NULL for system default
> - *     @rsrc: but mask of resource to release
> - *
> - *     This function releases resources previously locked by vga_get()
> - *     or vga_tryget(). The resources aren't disabled right away, so
> - *     that a subsequence vga_get() on the same card will succeed
> - *     immediately. Resources have a counter, so locks are only
> - *     released if the counter reaches 0.
> - */
> -
>  #if defined(CONFIG_VGA_ARB)
>  extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
>  #else
> @@ -168,25 +122,6 @@ extern void vga_put(struct pci_dev *pdev, unsigned int rsrc);
>  #endif
>
>
> -/**
> - *     vga_default_device
> - *
> - *     This can be defined by the platform. The default implementation
> - *     is rather dumb and will probably only work properly on single
> - *     vga card setups and/or x86 platforms.
> - *
> - *     If your VGA default device is not PCI, you'll have to return
> - *     NULL here. In this case, I assume it will not conflict with
> - *     any PCI card. If this is not true, I'll have to define two archs
> - *     hooks for enabling/disabling the VGA default device if that is
> - *     possible. This may be a problem with real _ISA_ VGA cards, in
> - *     addition to a PCI one. I don't know at this point how to deal
> - *     with that card. Can theirs IOs be disabled at all ? If not, then
> - *     I suppose it's a matter of having the proper arch hook telling
> - *     us about it, so we basically never allow anybody to succeed a
> - *     vga_get()...
> - */
> -
>  #ifdef CONFIG_VGA_ARB
>  extern struct pci_dev *vga_default_device(void);
>  extern void vga_set_default_device(struct pci_dev *pdev);
> @@ -195,14 +130,11 @@ static inline struct pci_dev *vga_default_device(void) { return NULL; };
>  static inline void vga_set_default_device(struct pci_dev *pdev) { };
>  #endif
>
> -/**
> - *     vga_conflicts
> - *
> - *     Architectures should define this if they have several
> - *     independent PCI domains that can afford concurrent VGA
> - *     decoding
> +/*
> + * Architectures should define this if they have several
> + * independent PCI domains that can afford concurrent VGA
> + * decoding
>   */
> -
>  #ifndef __ARCH_HAS_VGA_CONFLICT
>  static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
>  {
> @@ -210,34 +142,6 @@ static inline int vga_conflicts(struct pci_dev *p1, struct pci_dev *p2)
>  }
>  #endif
>
> -/**
> - *     vga_client_register
> - *
> - *     @pdev: pci device of the VGA client
> - *     @cookie: client cookie to be used in callbacks
> - *     @irq_set_state: irq state change callback
> - *     @set_vga_decode: vga decode change callback
> - *
> - *     return value: 0 on success, -1 on failure
> - *     Register a client with the VGA arbitration logic
> - *
> - *     Clients have two callback mechanisms they can use.
> - *     irq enable/disable callback -
> - *             If a client can't disable its GPUs VGA resources, then we
> - *             need to be able to ask it to turn off its irqs when we
> - *             turn off its mem and io decoding.
> - *     set_vga_decode
> - *             If a client can disable its GPU VGA resource, it will
> - *             get a callback from this to set the encode/decode state
> - *
> - * Rationale: we cannot disable VGA decode resources unconditionally
> - * some single GPU laptops seem to require ACPI or BIOS access to the
> - * VGA registers to control things like backlights etc.
> - * Hopefully newer multi-GPU laptops do something saner, and desktops
> - * won't have any special ACPI for this.
> - * They driver will get a callback when VGA arbitration is first used
> - * by userspace since we some older X servers have issues.
> - */
>  #if defined(CONFIG_VGA_ARB)
>  int vga_client_register(struct pci_dev *pdev, void *cookie,
>                         void (*irq_set_state)(void *cookie, bool state),
> --
> 2.8.1
>

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 19/21] drm: document drm_display_info
  2016-08-12 20:48 ` [PATCH 19/21] drm: document drm_display_info Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> We seem to have a bit a mess in how to describe the bus formats, with
> a multitude of competing ways. Might be best to consolidate it all and
> use MEDIA_BUS_FMT_ also for the hdmi color formats and high color
> modes.
>
> Also move all the display_info related functions into drm_connector.c
> (there's only one) to group it all together. I did decided against
> also moving the edid related display info functions, they seem to fit
> better in drm_edid.c. Instead sprinkle a few cross references around.
> While at that reduce the kerneldoc for static functions, there's not
> point in documenting internals with that much detail really.
>
> v2: Fix typo and move misplaced hunk (Sean).
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  drivers/gpu/drm/drm_connector.c | 34 ++++++++++++++++++++++
>  drivers/gpu/drm/drm_crtc.c      | 34 ----------------------
>  drivers/gpu/drm/drm_edid.c      | 23 +++------------
>  include/drm/drm_connector.h     | 63 ++++++++++++++++++++++++++++++++++++++---
>  include/drm/drm_crtc.h          |  4 ---
>  5 files changed, 97 insertions(+), 61 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 6a0551744d13..26bb78c76481 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -506,6 +506,40 @@ static const struct drm_prop_enum_list drm_dpms_enum_list[] = {
>  };
>  DRM_ENUM_NAME_FN(drm_get_dpms_name, drm_dpms_enum_list)
>
> +/**
> + * drm_display_info_set_bus_formats - set the supported bus formats
> + * @info: display info to store bus formats in
> + * @formats: array containing the supported bus formats
> + * @num_formats: the number of entries in the fmts array
> + *
> + * Store the supported bus formats in display info structure.
> + * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for
> + * a full list of available formats.
> + */
> +int drm_display_info_set_bus_formats(struct drm_display_info *info,
> +                                    const u32 *formats,
> +                                    unsigned int num_formats)
> +{
> +       u32 *fmts = NULL;
> +
> +       if (!formats && num_formats)
> +               return -EINVAL;
> +
> +       if (formats && num_formats) {
> +               fmts = kmemdup(formats, sizeof(*formats) * num_formats,
> +                              GFP_KERNEL);
> +               if (!fmts)
> +                       return -ENOMEM;
> +       }
> +
> +       kfree(info->bus_formats);
> +       info->bus_formats = fmts;
> +       info->num_bus_formats = num_formats;
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL(drm_display_info_set_bus_formats);
> +
>  /* Optional connector properties. */
>  static const struct drm_prop_enum_list drm_scaling_mode_enum_list[] = {
>         { DRM_MODE_SCALE_NONE, "None" },
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 07eba82a9998..d228c41b572b 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -419,40 +419,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
>  }
>  EXPORT_SYMBOL(drm_crtc_cleanup);
>
> -/**
> - * drm_display_info_set_bus_formats - set the supported bus formats
> - * @info: display info to store bus formats in
> - * @formats: array containing the supported bus formats
> - * @num_formats: the number of entries in the fmts array
> - *
> - * Store the supported bus formats in display info structure.
> - * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for
> - * a full list of available formats.
> - */
> -int drm_display_info_set_bus_formats(struct drm_display_info *info,
> -                                    const u32 *formats,
> -                                    unsigned int num_formats)
> -{
> -       u32 *fmts = NULL;
> -
> -       if (!formats && num_formats)
> -               return -EINVAL;
> -
> -       if (formats && num_formats) {
> -               fmts = kmemdup(formats, sizeof(*formats) * num_formats,
> -                              GFP_KERNEL);
> -               if (!fmts)
> -                       return -ENOMEM;
> -       }
> -
> -       kfree(info->bus_formats);
> -       info->bus_formats = fmts;
> -       info->num_bus_formats = num_formats;
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL(drm_display_info_set_bus_formats);
> -
>  static int drm_encoder_register_all(struct drm_device *dev)
>  {
>         struct drm_encoder *encoder;
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index c071bd635160..9b1ec64d579a 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -3732,14 +3732,7 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
>  }
>  EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
>
> -/**
> - * drm_assign_hdmi_deep_color_info - detect whether monitor supports
> - * hdmi deep color modes and update drm_display_info if so.
> - * @edid: monitor EDID information
> - * @info: Updated with maximum supported deep color bpc and color format
> - *        if deep color supported.
> - * @connector: DRM connector, used only for debug output
> - *
> +/*
>   * Parse the CEA extension according to CEA-861-B.
>   * Return true if HDMI deep color supported, false if not or unknown.
>   */
> @@ -3833,16 +3826,6 @@ static bool drm_assign_hdmi_deep_color_info(struct edid *edid,
>         return false;
>  }
>
> -/**
> - * drm_add_display_info - pull display info out if present
> - * @edid: EDID data
> - * @info: display info (attached to connector)
> - * @connector: connector whose edid is used to build display info
> - *
> - * Grab any available display info and stuff it into the drm_display_info
> - * structure that's part of the connector.  Useful for tracking bpp and
> - * color spaces.
> - */
>  static void drm_add_display_info(struct edid *edid,
>                                   struct drm_display_info *info,
>                                   struct drm_connector *connector)
> @@ -4063,7 +4046,9 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
>   * @connector: connector we're probing
>   * @edid: EDID data
>   *
> - * Add the specified modes to the connector's mode list.
> + * Add the specified modes to the connector's mode list. Also fills out the
> + * &drm_display_info structure in @connector with any information which can be
> + * derived from the edid.
>   *
>   * Return: The number of modes added or 0 if we couldn't find any.
>   */
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index bc88a5575792..f1576db6c044 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -84,28 +84,69 @@ enum subpixel_order {
>         SubPixelNone,
>  };
>
> -/*
> - * Describes a given display (e.g. CRT or flat panel) and its limitations.
> +/**
> + * struct drm_display_info - runtime data about the connected sink
> + *
> + * Describes a given display (e.g. CRT or flat panel) and its limitations. For
> + * fixed display sinks like built-in panels there's not much difference between
> + * this and struct &drm_connector. But for sinks with a real cable this
> + * structure is meant to describe all the things at the other end of the cable.
> + *
> + * For sinks which provide an EDID this can be filled out by calling
> + * drm_add_edid_modes().
>   */
>  struct drm_display_info {
> +       /**
> +        * @name: Name of the display.
> +        */
>         char name[DRM_DISPLAY_INFO_LEN];
>
> -       /* Physical size */
> +       /**
> +        * @width_mm: Physical width in mm.
> +        */
>          unsigned int width_mm;
> +       /**
> +        * @height_mm: Physical height in mm.
> +        */
>         unsigned int height_mm;
>
> +       /**
> +        * @pixel_clock: Maximum pixel clock supported by the sink, in units of
> +        * 100Hz. This mismatches the clok in &drm_display_mode (which is in
> +        * kHZ), because that's what the EDID uses as base unit.
> +        */
>         unsigned int pixel_clock;
> +       /**
> +        * @bpc: Maximum bits per color channel. Used by HDMI and DP outputs.
> +        */
>         unsigned int bpc;
>
> +       /**
> +        * @subpixel_order: Subpixel order of LCD panels.
> +        */
>         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)
>
> +       /**
> +        * @color_formats: HDMI Color formats, selects between RGB and YCrCb
> +        * modes. Used DRM_COLOR_FORMAT\_ defines, which are _not_ the same ones
> +        * as used to describe the pixel format in framebuffers, and also don't
> +        * match the formats in @bus_formats which are shared with v4l.
> +        */
>         u32 color_formats;
>
> +       /**
> +        * @bus_formats: Pixel data format on the wire, somewhat redundant with
> +        * @color_formats. Array of size @num_bus_formats encoded using
> +        * MEDIA_BUS_FMT\_ defines shared with v4l and media drivers.
> +        */
>         const u32 *bus_formats;
> +       /**
> +        * @num_bus_formats: Size of @bus_formats array.
> +        */
>         unsigned int num_bus_formats;
>
>  #define DRM_BUS_FLAG_DE_LOW            (1<<0)
> @@ -115,14 +156,28 @@ struct drm_display_info {
>  /* drive data on neg. edge */
>  #define DRM_BUS_FLAG_PIXDATA_NEGEDGE   (1<<3)
>
> +       /**
> +        * @bus_flags: Additional information (like pixel signal polarity) for
> +        * the pixel data on the bus, using DRM_BUS_FLAGS\_ defines.
> +        */
>         u32 bus_flags;
>
> -       /* Mask of supported hdmi deep color modes */
> +       /**
> +        * @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
> +        * more stuff redundant with @bus_formats.
> +        */
>         u8 edid_hdmi_dc_modes;
>
> +       /**
> +        * @cea_rev: CEA revision of the HDMI sink.
> +        */
>         u8 cea_rev;
>  };
>
> +int drm_display_info_set_bus_formats(struct drm_display_info *info,
> +                                    const u32 *formats,
> +                                    unsigned int num_formats);
> +
>  /**
>   * struct drm_connector_state - mutable connector state
>   * @connector: backpointer to the connector
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index e30ea0be6417..3fa0275e509f 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -2208,10 +2208,6 @@ 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_display_info_set_bus_formats(struct drm_display_info *info,
> -                                           const u32 *formats,
> -                                           unsigned int num_formats);
> -
>  static inline bool drm_property_type_is(struct drm_property *property,
>                 uint32_t type)
>  {
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 17/21] drm: Update connector documentation
  2016-08-12 20:48 ` [PATCH 17/21] drm: Update connector documentation Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> - Shuffle docs from drm-kms.rst into the structure docs where it makes
>   sense.
> - Put the remaining bits into a new overview section.
>
> One thing I've changed is around probing: Old docs says that you
> _must_ use the probe helpers, which isn't correct. Helpers are always
> optional.
>
> v2: Review from Sean.
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/drm-kms.rst   | 170 ++--------------------------------------
>  drivers/gpu/drm/drm_connector.c |  33 +++++++-
>  include/drm/drm_connector.h     |  57 +++++++++++++-
>  3 files changed, 94 insertions(+), 166 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 6e7ab57924f0..fa948b4e029b 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -110,8 +110,14 @@ Display Modes Function Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_modes.c
>     :export:
>
> -Connector Display Sink Abstraction
> -==================================
> +Connector Abstraction
> +=====================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_connector.c
> +   :doc: overview
> +
> +Connector Functions Reference
> +-----------------------------
>
>  .. kernel-doc:: include/drm/drm_connector.h
>     :internal:
> @@ -232,166 +238,6 @@ encoders unattached at initialization time. Applications (or the fbdev
>  compatibility layer when implemented) are responsible for attaching the
>  encoders they want to use to a CRTC.
>
> -Connectors (:c:type:`struct drm_connector <drm_connector>`)
> ------------------------------------------------------------
> -
> -A connector is the final destination for pixel data on a device, and
> -usually connects directly to an external display device like a monitor
> -or laptop panel. A connector can only be attached to one encoder at a
> -time. The connector is also the structure where information about the
> -attached display is kept, so it contains fields for display data, EDID
> -data, DPMS & connection status, and information about modes supported on
> -the attached displays.
> -
> -Connector Initialization
> -~~~~~~~~~~~~~~~~~~~~~~~~
> -
> -Finally a KMS driver must create, initialize, register and attach at
> -least one :c:type:`struct drm_connector <drm_connector>`
> -instance. The instance is created as other KMS objects and initialized
> -by setting the following fields.
> -
> -interlace_allowed
> -    Whether the connector can handle interlaced modes.
> -
> -doublescan_allowed
> -    Whether the connector can handle doublescan.
> -
> -display_info
> -    Display information is filled from EDID information when a display
> -    is detected. For non hot-pluggable displays such as flat panels in
> -    embedded systems, the driver should initialize the
> -    display_info.width_mm and display_info.height_mm fields with the
> -    physical size of the display.
> -
> -polled
> -    Connector polling mode, a combination of
> -
> -    DRM_CONNECTOR_POLL_HPD
> -        The connector generates hotplug events and doesn't need to be
> -        periodically polled. The CONNECT and DISCONNECT flags must not
> -        be set together with the HPD flag.
> -
> -    DRM_CONNECTOR_POLL_CONNECT
> -        Periodically poll the connector for connection.
> -
> -    DRM_CONNECTOR_POLL_DISCONNECT
> -        Periodically poll the connector for disconnection.
> -
> -    Set to 0 for connectors that don't support connection status
> -    discovery.
> -
> -The connector is then registered with a call to
> -:c:func:`drm_connector_init()` with a pointer to the connector
> -functions and a connector type, and exposed through sysfs with a call to
> -:c:func:`drm_connector_register()`.
> -
> -Supported connector types are
> -
> --  DRM_MODE_CONNECTOR_VGA
> --  DRM_MODE_CONNECTOR_DVII
> --  DRM_MODE_CONNECTOR_DVID
> --  DRM_MODE_CONNECTOR_DVIA
> --  DRM_MODE_CONNECTOR_Composite
> --  DRM_MODE_CONNECTOR_SVIDEO
> --  DRM_MODE_CONNECTOR_LVDS
> --  DRM_MODE_CONNECTOR_Component
> --  DRM_MODE_CONNECTOR_9PinDIN
> --  DRM_MODE_CONNECTOR_DisplayPort
> --  DRM_MODE_CONNECTOR_HDMIA
> --  DRM_MODE_CONNECTOR_HDMIB
> --  DRM_MODE_CONNECTOR_TV
> --  DRM_MODE_CONNECTOR_eDP
> --  DRM_MODE_CONNECTOR_VIRTUAL
> -
> -Connectors must be attached to an encoder to be used. For devices that
> -map connectors to encoders 1:1, the connector should be attached at
> -initialization time with a call to
> -:c:func:`drm_mode_connector_attach_encoder()`. The driver must
> -also set the :c:type:`struct drm_connector <drm_connector>`
> -encoder field to point to the attached encoder.
> -
> -Finally, drivers must initialize the connectors state change detection
> -with a call to :c:func:`drm_kms_helper_poll_init()`. If at least
> -one connector is pollable but can't generate hotplug interrupts
> -(indicated by the DRM_CONNECTOR_POLL_CONNECT and
> -DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will
> -automatically be queued to periodically poll for changes. Connectors
> -that can generate hotplug interrupts must be marked with the
> -DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must
> -call :c:func:`drm_helper_hpd_irq_event()`. The function will
> -queue a delayed work to check the state of all connectors, but no
> -periodic polling will be done.
> -
> -Connector Operations
> -~~~~~~~~~~~~~~~~~~~~
> -
> -    **Note**
> -
> -    Unless otherwise state, all operations are mandatory.
> -
> -DPMS
> -''''
> -
> -void (\*dpms)(struct drm_connector \*connector, int mode);
> -The DPMS operation sets the power state of a connector. The mode
> -argument is one of
> -
> --  DRM_MODE_DPMS_ON
> -
> --  DRM_MODE_DPMS_STANDBY
> -
> --  DRM_MODE_DPMS_SUSPEND
> -
> --  DRM_MODE_DPMS_OFF
> -
> -In all but DPMS_ON mode the encoder to which the connector is attached
> -should put the display in low-power mode by driving its signals
> -appropriately. If more than one connector is attached to the encoder
> -care should be taken not to change the power state of other displays as
> -a side effect. Low-power mode should be propagated to the encoders and
> -CRTCs when all related connectors are put in low-power mode.
> -
> -Modes
> -'''''
> -
> -int (\*fill_modes)(struct drm_connector \*connector, uint32_t
> -max_width, uint32_t max_height);
> -Fill the mode list with all supported modes for the connector. If the
> -``max_width`` and ``max_height`` arguments are non-zero, the
> -implementation must ignore all modes wider than ``max_width`` or higher
> -than ``max_height``.
> -
> -The connector must also fill in this operation its display_info
> -width_mm and height_mm fields with the connected display physical size
> -in millimeters. The fields should be set to 0 if the value isn't known
> -or is not applicable (for instance for projector devices).
> -
> -Connection Status
> -'''''''''''''''''
> -
> -The connection status is updated through polling or hotplug events when
> -supported (see ?). The status value is reported to userspace through
> -ioctls and must not be used inside the driver, as it only gets
> -initialized by a call to :c:func:`drm_mode_getconnector()` from
> -userspace.
> -
> -enum drm_connector_status (\*detect)(struct drm_connector
> -\*connector, bool force);
> -Check to see if anything is attached to the connector. The ``force``
> -parameter is set to false whilst polling or to true when checking the
> -connector due to user request. ``force`` can be used by the driver to
> -avoid expensive, destructive operations during automated probing.
> -
> -Return connector_status_connected if something is connected to the
> -connector, connector_status_disconnected if nothing is connected and
> -connector_status_unknown if the connection state isn't known.
> -
> -Drivers should only return connector_status_connected if the
> -connection status has really been probed as connected. Connectors that
> -can't detect the connection status, or failed connection status probes,
> -should return connector_status_unknown.
> -
>  Cleanup
>  -------
>
> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
> index 99ece6758061..6a0551744d13 100644
> --- a/drivers/gpu/drm/drm_connector.c
> +++ b/drivers/gpu/drm/drm_connector.c
> @@ -27,6 +27,37 @@
>  #include "drm_crtc_internal.h"
>  #include "drm_internal.h"
>
> +/**
> + * DOC: overview
> + *
> + * In DRM connectors are the general abstraction for display sinks, and include
> + * als fixed panels or anything else that can display pixels in some form. As
> + * opposed to all other KMS objects representing hardware (like CRTC, encoder or
> + * plane abstractions) connectors can be hotplugged and unplugged at runtime.
> + * Hence they are reference-counted using drm_connector_reference() and
> + * drm_connector_unreference().
> + *
> + * KMS driver must create, initialize, register and attach at a struct
> + * &drm_connector for each such sink. The instance is created as other KMS
> + * objects and initialized by setting the following fields.
> + *
> + * The connector is then registered with a call to drm_connector_init() with a
> + * pointer to the connector functions and a connector type, and exposed through
> + * sysfs with a call to drm_connector_register().
> + *
> + * Connectors must be attached to an encoder to be used. For devices that map
> + * connectors to encoders 1:1, the connector should be attached at
> + * initialization time with a call to drm_mode_connector_attach_encoder(). The
> + * driver must also set the struct &drm_connector encoder field to point to the
> + * attached encoder.
> + *
> + * For connectors which are not fixed (like built-in panels) the driver needs to
> + * support hotplug notifications. The simplest way to do that is by using the
> + * probe helpers, see drm_kms_helper_poll_init() for connectors which don't have
> + * hardware support for hotplug interrupts. Connectors with hardware hotplug
> + * support can instead use e.g. drm_helper_hpd_irq_event().
> + */
> +
>  struct drm_conn_prop_enum_list {
>         int type;
>         const char *name;
> @@ -77,7 +108,7 @@ void drm_connector_ida_destroy(void)
>   * 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
> + * The kernel supports per-connector configuration 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
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index ec2bea0b1b38..3537b7d8259b 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -42,9 +42,36 @@ enum drm_connector_force {
>         DRM_FORCE_ON_DIGITAL, /* for DVI-I use digital connector */
>  };
>
> +/**
> + * enum drm_connector_status - status for a &drm_connector
> + *
> + * This enum is used to track the connector status. There are no separate
> + * #defines for the uapi!
> + */
>  enum drm_connector_status {
> +       /**
> +        * @connector_status_connected: The connector is definitely connected to
> +        * a sink device, and can be enabled.
> +        */
>         connector_status_connected = 1,
> +       /**
> +        * @connector_status_disconnected: The connector isn't connected to a
> +        * sink device which can be autodetect. For digital outputs like DP or
> +        * HDMI (which can be realiable probed) this means there's really
> +        * nothing there. It is driver-dependent whether a connector with this
> +        * status can be lit up or not.
> +        */
>         connector_status_disconnected = 2,
> +       /**
> +        * @connector_status_unknown: The connector's status could not be
> +        * reliably detected. This happens when probing would either cause
> +        * flicker (like load-detection when the connector is in use), or when a
> +        * hardware resource isn't available (like when load-detection needs a
> +        * free CRTC). It should be possible to light up the connector with one
> +        * of the listed fallback modes. For default configuration userspace
> +        * should only try to light up connectors with unknown status when
> +        * there's not connector with @connector_status_connected.
> +        */
>         connector_status_unknown = 3,
>  };
>
> @@ -416,11 +443,9 @@ struct drm_cmdline_mode {
>   * @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
> @@ -485,6 +510,13 @@ struct drm_connector {
>         /* these are modes added by probing with DDC or the BIOS */
>         struct list_head probed_modes;
>
> +       /**
> +        * @display_info: Display information is filled from EDID information
> +        * when a display is detected. For non hot-pluggable displays such as
> +        * flat panels in embedded systems, the driver should initialize the
> +        * display_info.width_mm and display_info.height_mm fields with the
> +        * physical size of the display.
> +        */
>         struct drm_display_info display_info;
>         const struct drm_connector_funcs *funcs;
>
> @@ -519,7 +551,26 @@ struct drm_connector {
>  /* DACs should rarely do this without a lot of testing */
>  #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
>
> -       uint8_t polled; /* DRM_CONNECTOR_POLL_* */
> +       /**
> +        * @polled:
> +        *
> +        * Connector polling mode, a combination of
> +        *
> +        * DRM_CONNECTOR_POLL_HPD
> +        *     The connector generates hotplug events and doesn't need to be
> +        *     periodically polled. The CONNECT and DISCONNECT flags must not
> +        *     be set together with the HPD flag.
> +        *
> +        * DRM_CONNECTOR_POLL_CONNECT
> +        *     Periodically poll the connector for connection.
> +        *
> +        * DRM_CONNECTOR_POLL_DISCONNECT
> +        *     Periodically poll the connector for disconnection.
> +        *
> +        * Set to 0 for connectors that don't support connection status
> +        * discovery.
> +        */
> +       uint8_t polled;
>
>         /* requested DPMS state */
>         int dpms;
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 16/21] drm: Don't export dp-aux devnode functions
  2016-08-12 20:48 ` [PATCH 16/21] drm: Don't export dp-aux devnode functions Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> They're only used internally within the dp helpers. Also nuke the
> kerneldoc (we only document the driver interface in the drm shared
> functions). And move the header file from the public include/
> directory to the source files into drm_crtc_helper_internal.h, similar
> to how we already have drm_crtc_internal.h.
>
> While at it also move drm_fb_helper_modinit since that belongs in
> there, too.
>
> I noticed this all since I spotted kerneldoc which wasn't pulled into
> the rst templates.
>
> v2: Update Copyright date.
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Rafael Antognolli <rafael.antognolli@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
> ---
>  drivers/gpu/drm/drm_crtc_helper_internal.h | 58 ++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_dp_aux_dev.c           | 19 ++-------
>  drivers/gpu/drm/drm_dp_helper.c            |  3 +-
>  drivers/gpu/drm/drm_kms_helper_common.c    |  3 +-
>  include/drm/drm_dp_aux_dev.h               | 62 ------------------------------
>  include/drm/drm_fb_helper.h                |  1 -
>  6 files changed, 65 insertions(+), 81 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_crtc_helper_internal.h
>  delete mode 100644 include/drm/drm_dp_aux_dev.h
>
> diff --git a/drivers/gpu/drm/drm_crtc_helper_internal.h b/drivers/gpu/drm/drm_crtc_helper_internal.h
> new file mode 100644
> index 000000000000..4e6b57ae7188
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_crtc_helper_internal.h
> @@ -0,0 +1,58 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +/*
> + * This header file contains mode setting related functions and definitions
> + * which are only used within the drm kms helper module as internal
> + * implementation details and are not exported to drivers.
> + */
> +
> +#include <drm/drm_dp_helper.h>
> +
> +/* drm_fb_helper.c */
> +int drm_fb_helper_modinit(void);
> +
> +/* drm_dp_aux_dev.c */
> +#ifdef CONFIG_DRM_DP_AUX_CHARDEV
> +int drm_dp_aux_dev_init(void);
> +void drm_dp_aux_dev_exit(void);
> +int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
> +void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
> +#else
> +static inline int drm_dp_aux_dev_init(void)
> +{
> +       return 0;
> +}
> +
> +static inline void drm_dp_aux_dev_exit(void)
> +{
> +}
> +
> +static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
> +{
> +       return 0;
> +}
> +
> +static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
> +{
> +}
> +#endif
> diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c
> index 734f86a345f6..ec1ed94b2390 100644
> --- a/drivers/gpu/drm/drm_dp_aux_dev.c
> +++ b/drivers/gpu/drm/drm_dp_aux_dev.c
> @@ -36,6 +36,8 @@
>  #include <drm/drm_crtc.h>
>  #include <drm/drmP.h>
>
> +#include "drm_crtc_helper_internal.h"
> +
>  struct drm_dp_aux_dev {
>         unsigned index;
>         struct drm_dp_aux *aux;
> @@ -283,12 +285,7 @@ static int auxdev_wait_atomic_t(atomic_t *p)
>         schedule();
>         return 0;
>  }
> -/**
> - * drm_dp_aux_unregister_devnode() - unregister a devnode for this aux channel
> - * @aux: DisplayPort AUX channel
> - *
> - * Returns 0 on success or a negative error code on failure.
> - */
> +
>  void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
>  {
>         struct drm_dp_aux_dev *aux_dev;
> @@ -314,14 +311,7 @@ void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
>         DRM_DEBUG("drm_dp_aux_dev: aux [%s] unregistering\n", aux->name);
>         kref_put(&aux_dev->refcount, release_drm_dp_aux_dev);
>  }
> -EXPORT_SYMBOL(drm_dp_aux_unregister_devnode);
>
> -/**
> - * drm_dp_aux_register_devnode() - register a devnode for this aux channel
> - * @aux: DisplayPort AUX channel
> - *
> - * Returns 0 on success or a negative error code on failure.
> - */
>  int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
>  {
>         struct drm_dp_aux_dev *aux_dev;
> @@ -347,7 +337,6 @@ error:
>         drm_dp_aux_unregister_devnode(aux);
>         return res;
>  }
> -EXPORT_SYMBOL(drm_dp_aux_register_devnode);
>
>  int drm_dp_aux_dev_init(void)
>  {
> @@ -369,11 +358,9 @@ out:
>         class_destroy(drm_dp_aux_dev_class);
>         return res;
>  }
> -EXPORT_SYMBOL(drm_dp_aux_dev_init);
>
>  void drm_dp_aux_dev_exit(void)
>  {
>         unregister_chrdev(drm_dev_major, "aux");
>         class_destroy(drm_dp_aux_dev_class);
>  }
> -EXPORT_SYMBOL(drm_dp_aux_dev_exit);
> diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
> index 5d20255f3db3..031c4d335b08 100644
> --- a/drivers/gpu/drm/drm_dp_helper.c
> +++ b/drivers/gpu/drm/drm_dp_helper.c
> @@ -28,9 +28,10 @@
>  #include <linux/sched.h>
>  #include <linux/i2c.h>
>  #include <drm/drm_dp_helper.h>
> -#include <drm/drm_dp_aux_dev.h>
>  #include <drm/drmP.h>
>
> +#include "drm_crtc_helper_internal.h"
> +
>  /**
>   * DOC: dp helpers
>   *
> diff --git a/drivers/gpu/drm/drm_kms_helper_common.c b/drivers/gpu/drm/drm_kms_helper_common.c
> index 3187c4bb01cb..45db36cd3d20 100644
> --- a/drivers/gpu/drm/drm_kms_helper_common.c
> +++ b/drivers/gpu/drm/drm_kms_helper_common.c
> @@ -27,7 +27,8 @@
>
>  #include <drm/drmP.h>
>  #include <drm/drm_fb_helper.h>
> -#include <drm/drm_dp_aux_dev.h>
> +
> +#include "drm_crtc_helper_internal.h"
>
>  MODULE_AUTHOR("David Airlie, Jesse Barnes");
>  MODULE_DESCRIPTION("DRM KMS helper");
> diff --git a/include/drm/drm_dp_aux_dev.h b/include/drm/drm_dp_aux_dev.h
> deleted file mode 100644
> index 1b76d990d8ab..000000000000
> --- a/include/drm/drm_dp_aux_dev.h
> +++ /dev/null
> @@ -1,62 +0,0 @@
> -/*
> - * Copyright © 2015 Intel Corporation
> - *
> - * Permission is hereby granted, free of charge, to any person obtaining a
> - * copy of this software and associated documentation files (the "Software"),
> - * to deal in the Software without restriction, including without limitation
> - * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> - * and/or sell copies of the Software, and to permit persons to whom the
> - * Software is furnished to do so, subject to the following conditions:
> - *
> - * The above copyright notice and this permission notice (including the next
> - * paragraph) shall be included in all copies or substantial portions of the
> - * Software.
> - *
> - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> - * IN THE SOFTWARE.
> - *
> - * Authors:
> - *    Rafael Antognolli <rafael.antognolli@intel.com>
> - *
> - */
> -
> -#ifndef DRM_DP_AUX_DEV
> -#define DRM_DP_AUX_DEV
> -
> -#include <drm/drm_dp_helper.h>
> -
> -#ifdef CONFIG_DRM_DP_AUX_CHARDEV
> -
> -int drm_dp_aux_dev_init(void);
> -void drm_dp_aux_dev_exit(void);
> -int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
> -void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
> -
> -#else
> -
> -static inline int drm_dp_aux_dev_init(void)
> -{
> -       return 0;
> -}
> -
> -static inline void drm_dp_aux_dev_exit(void)
> -{
> -}
> -
> -static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
> -{
> -       return 0;
> -}
> -
> -static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
> -{
> -}
> -
> -#endif
> -
> -#endif
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 130c324f1aee..97889a90ff23 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -216,7 +216,6 @@ struct drm_fb_helper {
>  };
>
>  #ifdef CONFIG_DRM_FBDEV_EMULATION
> -int drm_fb_helper_modinit(void);
>  void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
>                            const struct drm_fb_helper_funcs *funcs);
>  int drm_fb_helper_init(struct drm_device *dev,
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc]
  2016-08-12 20:48 ` [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc] Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> While reviewing docs I spotted that we have a few functions that
> really just don't fit into their containing helper library section.
> Extract them and shovel them all into a new library for random one-off
> aux stuff.
>
> v2: Remove wrongly added files for real.
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/drm-kms-helpers.rst |   9 ++
>  drivers/gpu/drm/Makefile              |   2 +-
>  drivers/gpu/drm/drm_crtc_helper.c     |  56 -------------
>  drivers/gpu/drm/drm_modeset_helper.c  | 153 ++++++++++++++++++++++++++++++++++
>  drivers/gpu/drm/drm_plane_helper.c    |  66 ---------------
>  include/drm/drm_atomic_helper.h       |   2 +
>  include/drm/drm_crtc_helper.h         |   6 +-
>  include/drm/drm_modeset_helper.h      |  36 ++++++++
>  include/drm/drm_plane_helper.h        |   4 +-
>  9 files changed, 203 insertions(+), 131 deletions(-)
>  create mode 100644 drivers/gpu/drm/drm_modeset_helper.c
>  create mode 100644 include/drm/drm_modeset_helper.h
>
> diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
> index 34f755bc9133..59fa3c11efab 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -258,3 +258,12 @@ Tile group
>
>  .. kernel-doc:: drivers/gpu/drm/drm_crtc.c
>     :doc: Tile group
> +
> +Auxiliary Modeset Helpers
> +=========================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
> +   :doc: aux kms helpers
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_modeset_helper.c
> +   :export:
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 0238bf8bc8c3..a5824d926dc9 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -24,7 +24,7 @@ drm-$(CONFIG_AGP) += drm_agpsupport.o
>  drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o \
>                 drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
>                 drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
> -               drm_simple_kms_helper.o drm_blend.o
> +               drm_simple_kms_helper.o drm_blend.o drm_modeset_helper.o
>
>  drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
>  drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 604d3ef72ffa..5d2cb138eba6 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -75,35 +75,6 @@
>   */
>
>  /**
> - * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
> - *                                             connector list
> - * @dev: drm device to operate on
> - *
> - * Some userspace presumes that the first connected connector is the main
> - * display, where it's supposed to display e.g. the login screen. For
> - * laptops, this should be the main panel. Use this function to sort all
> - * (eDP/LVDS) panels to the front of the connector list, instead of
> - * painstakingly trying to initialize them in the right order.
> - */
> -void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
> -{
> -       struct drm_connector *connector, *tmp;
> -       struct list_head panel_list;
> -
> -       INIT_LIST_HEAD(&panel_list);
> -
> -       list_for_each_entry_safe(connector, tmp,
> -                                &dev->mode_config.connector_list, head) {
> -               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> -                   connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> -                       list_move_tail(&connector->head, &panel_list);
> -       }
> -
> -       list_splice(&panel_list, &dev->mode_config.connector_list);
> -}
> -EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
> -
> -/**
>   * drm_helper_encoder_in_use - check if a given encoder is in use
>   * @encoder: encoder to check
>   *
> @@ -913,33 +884,6 @@ int drm_helper_connector_dpms(struct drm_connector *connector, int mode)
>  EXPORT_SYMBOL(drm_helper_connector_dpms);
>
>  /**
> - * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
> - * @fb: drm_framebuffer object to fill out
> - * @mode_cmd: metadata from the userspace fb creation request
> - *
> - * This helper can be used in a drivers fb_create callback to pre-fill the fb's
> - * metadata fields.
> - */
> -void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> -                                   const struct drm_mode_fb_cmd2 *mode_cmd)
> -{
> -       int i;
> -
> -       fb->width = mode_cmd->width;
> -       fb->height = mode_cmd->height;
> -       for (i = 0; i < 4; i++) {
> -               fb->pitches[i] = mode_cmd->pitches[i];
> -               fb->offsets[i] = mode_cmd->offsets[i];
> -               fb->modifier[i] = mode_cmd->modifier[i];
> -       }
> -       drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
> -                                   &fb->bits_per_pixel);
> -       fb->pixel_format = mode_cmd->pixel_format;
> -       fb->flags = mode_cmd->flags;
> -}
> -EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
> -
> -/**
>   * drm_helper_resume_force_mode - force-restore mode setting configuration
>   * @dev: drm_device which should be restored
>   *
> diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c
> new file mode 100644
> index 000000000000..1d45738f8f98
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_modeset_helper.c
> @@ -0,0 +1,153 @@
> +/*
> + * 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/drm_modeset_helper.h>
> +#include <drm/drm_plane_helper.h>
> +
> +/**
> + * DOC: aux kms helpers
> + *
> + * This helper library contains various one-off functions which don't really fit
> + * anywhere else in the DRM modeset helper library.
> + */
> +
> +/**
> + * drm_helper_move_panel_connectors_to_head() - move panels to the front in the
> + *                                             connector list
> + * @dev: drm device to operate on
> + *
> + * Some userspace presumes that the first connected connector is the main
> + * display, where it's supposed to display e.g. the login screen. For
> + * laptops, this should be the main panel. Use this function to sort all
> + * (eDP/LVDS) panels to the front of the connector list, instead of
> + * painstakingly trying to initialize them in the right order.
> + */
> +void drm_helper_move_panel_connectors_to_head(struct drm_device *dev)
> +{
> +       struct drm_connector *connector, *tmp;
> +       struct list_head panel_list;
> +
> +       INIT_LIST_HEAD(&panel_list);
> +
> +       list_for_each_entry_safe(connector, tmp,
> +                                &dev->mode_config.connector_list, head) {
> +               if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
> +                   connector->connector_type == DRM_MODE_CONNECTOR_eDP)
> +                       list_move_tail(&connector->head, &panel_list);
> +       }
> +
> +       list_splice(&panel_list, &dev->mode_config.connector_list);
> +}
> +EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head);
> +
> +/**
> + * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata
> + * @fb: drm_framebuffer object to fill out
> + * @mode_cmd: metadata from the userspace fb creation request
> + *
> + * This helper can be used in a drivers fb_create callback to pre-fill the fb's
> + * metadata fields.
> + */
> +void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> +                                   const struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +       int i;
> +
> +       fb->width = mode_cmd->width;
> +       fb->height = mode_cmd->height;
> +       for (i = 0; i < 4; i++) {
> +               fb->pitches[i] = mode_cmd->pitches[i];
> +               fb->offsets[i] = mode_cmd->offsets[i];
> +               fb->modifier[i] = mode_cmd->modifier[i];
> +       }
> +       drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth,
> +                                   &fb->bits_per_pixel);
> +       fb->pixel_format = mode_cmd->pixel_format;
> +       fb->flags = mode_cmd->flags;
> +}
> +EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct);
> +
> +/*
> + * This is the minimal list of formats that seem to be safe for modeset use
> + * with all current DRM drivers.  Most hardware can actually support more
> + * formats than this and drivers may specify a more accurate list when
> + * creating the primary plane.  However drivers that still call
> + * drm_plane_init() will use this minimal format list as the default.
> + */
> +static const uint32_t safe_modeset_formats[] = {
> +       DRM_FORMAT_XRGB8888,
> +       DRM_FORMAT_ARGB8888,
> +};
> +
> +static struct drm_plane *create_primary_plane(struct drm_device *dev)
> +{
> +       struct drm_plane *primary;
> +       int ret;
> +
> +       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> +       if (primary == NULL) {
> +               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> +               return NULL;
> +       }
> +
> +       /*
> +        * Remove the format_default field from drm_plane when dropping
> +        * this helper.
> +        */
> +       primary->format_default = true;
> +
> +       /* possible_crtc's will be filled in later by crtc_init */
> +       ret = drm_universal_plane_init(dev, primary, 0,
> +                                      &drm_primary_helper_funcs,
> +                                      safe_modeset_formats,
> +                                      ARRAY_SIZE(safe_modeset_formats),
> +                                      DRM_PLANE_TYPE_PRIMARY, NULL);
> +       if (ret) {
> +               kfree(primary);
> +               primary = NULL;
> +       }
> +
> +       return primary;
> +}
> +
> +/**
> + * drm_crtc_init - Legacy CRTC initialization function
> + * @dev: DRM device
> + * @crtc: CRTC object to init
> + * @funcs: callbacks for the new CRTC
> + *
> + * Initialize a CRTC object with a default helper-provided primary plane and no
> + * cursor plane.
> + *
> + * Returns:
> + * Zero on success, error code on failure.
> + */
> +int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                 const struct drm_crtc_funcs *funcs)
> +{
> +       struct drm_plane *primary;
> +
> +       primary = create_primary_plane(dev);
> +       return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
> +                                        NULL);
> +}
> +EXPORT_SYMBOL(drm_crtc_init);
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index b522aabd1ab0..50b9c1bfc6f6 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -64,18 +64,6 @@
>   */
>
>  /*
> - * This is the minimal list of formats that seem to be safe for modeset use
> - * with all current DRM drivers.  Most hardware can actually support more
> - * formats than this and drivers may specify a more accurate list when
> - * creating the primary plane.  However drivers that still call
> - * drm_plane_init() will use this minimal format list as the default.
> - */
> -static const uint32_t safe_modeset_formats[] = {
> -       DRM_FORMAT_XRGB8888,
> -       DRM_FORMAT_ARGB8888,
> -};
> -
> -/*
>   * Returns the connectors currently associated with a CRTC.  This function
>   * should be called twice:  once with a NULL connector list to retrieve
>   * the list size, and once with the properly allocated list to be filled in.
> @@ -438,60 +426,6 @@ const struct drm_plane_funcs drm_primary_helper_funcs = {
>  };
>  EXPORT_SYMBOL(drm_primary_helper_funcs);
>
> -static struct drm_plane *create_primary_plane(struct drm_device *dev)
> -{
> -       struct drm_plane *primary;
> -       int ret;
> -
> -       primary = kzalloc(sizeof(*primary), GFP_KERNEL);
> -       if (primary == NULL) {
> -               DRM_DEBUG_KMS("Failed to allocate primary plane\n");
> -               return NULL;
> -       }
> -
> -       /*
> -        * Remove the format_default field from drm_plane when dropping
> -        * this helper.
> -        */
> -       primary->format_default = true;
> -
> -       /* possible_crtc's will be filled in later by crtc_init */
> -       ret = drm_universal_plane_init(dev, primary, 0,
> -                                      &drm_primary_helper_funcs,
> -                                      safe_modeset_formats,
> -                                      ARRAY_SIZE(safe_modeset_formats),
> -                                      DRM_PLANE_TYPE_PRIMARY, NULL);
> -       if (ret) {
> -               kfree(primary);
> -               primary = NULL;
> -       }
> -
> -       return primary;
> -}
> -
> -/**
> - * drm_crtc_init - Legacy CRTC initialization function
> - * @dev: DRM device
> - * @crtc: CRTC object to init
> - * @funcs: callbacks for the new CRTC
> - *
> - * Initialize a CRTC object with a default helper-provided primary plane and no
> - * cursor plane.
> - *
> - * Returns:
> - * Zero on success, error code on failure.
> - */
> -int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> -                 const struct drm_crtc_funcs *funcs)
> -{
> -       struct drm_plane *primary;
> -
> -       primary = create_primary_plane(dev);
> -       return drm_crtc_init_with_planes(dev, crtc, primary, NULL, funcs,
> -                                        NULL);
> -}
> -EXPORT_SYMBOL(drm_crtc_init);
> -
>  int drm_plane_helper_commit(struct drm_plane *plane,
>                             struct drm_plane_state *plane_state,
>                             struct drm_framebuffer *old_fb)
> diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
> index d86ae5dcd7b4..5a02e499f32b 100644
> --- a/include/drm/drm_atomic_helper.h
> +++ b/include/drm/drm_atomic_helper.h
> @@ -29,6 +29,8 @@
>  #define DRM_ATOMIC_HELPER_H_
>
>  #include <drm/drm_crtc.h>
> +#include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_modeset_helper.h>
>
>  struct drm_atomic_state;
>
> diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
> index 4b37afa2b73b..982c299e435a 100644
> --- a/include/drm/drm_crtc_helper.h
> +++ b/include/drm/drm_crtc_helper.h
> @@ -41,6 +41,7 @@
>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_modeset_helper.h>
>
>  extern void drm_helper_disable_unused_functions(struct drm_device *dev);
>  extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
> @@ -53,11 +54,6 @@ extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
>
>  extern int drm_helper_connector_dpms(struct drm_connector *connector, int mode);
>
> -extern void drm_helper_move_panel_connectors_to_head(struct drm_device *);
> -
> -extern void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> -                                          const struct drm_mode_fb_cmd2 *mode_cmd);
> -
>  extern void drm_helper_resume_force_mode(struct drm_device *dev);
>
>  int drm_helper_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
> diff --git a/include/drm/drm_modeset_helper.h b/include/drm/drm_modeset_helper.h
> new file mode 100644
> index 000000000000..b8051d5abe10
> --- /dev/null
> +++ b/include/drm/drm_modeset_helper.h
> @@ -0,0 +1,36 @@
> +/*
> + * 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_KMS_HELPER_H__
> +#define __DRM_KMS_HELPER_H__
> +
> +#include <drm/drmP.h>
> +
> +void drm_helper_move_panel_connectors_to_head(struct drm_device *);
> +
> +void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
> +                                   const struct drm_mode_fb_cmd2 *mode_cmd);
> +
> +int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> +                 const struct drm_crtc_funcs *funcs);
> +
> +#endif
> diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
> index fbc8ecb3e5e8..c18959685c06 100644
> --- a/include/drm/drm_plane_helper.h
> +++ b/include/drm/drm_plane_helper.h
> @@ -27,6 +27,7 @@
>  #include <drm/drm_rect.h>
>  #include <drm/drm_crtc.h>
>  #include <drm/drm_modeset_helper_vtables.h>
> +#include <drm/drm_modeset_helper.h>
>
>  /*
>   * Drivers that don't allow primary plane scaling may pass this macro in place
> @@ -37,9 +38,6 @@
>   */
>  #define DRM_PLANE_HELPER_NO_SCALING (1<<16)
>
> -int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
> -                 const struct drm_crtc_funcs *funcs);
> -
>  int drm_plane_helper_check_state(struct drm_plane_state *state,
>                                  const struct drm_rect *clip,
>                                  int min_scale, int max_scale,
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup
  2016-08-12 20:48 ` [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
@ 2016-08-15 20:15   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-15 20:15 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 4:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> - Move the common vtable stuff to the top
> - Move "Tile Group" to a more appropriate heading level
> - Throw away the old intro for the crtc helpers (it's entirely stale,
>   e.g. helpers have become modular years ago), and replace it with a
>   general intro about the motivation behind helpers.
> - Reorder helpers to group them together a bit better, and explain
>   that grouping in the intro.
> - Make sure the introductory DOC section is always first.
>
> v2:
> - Remove bogus files accidentally added (Sean).
> - Spelling fixes (Sean).
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/drm-kms-helpers.rst | 208 +++++++++++++++++-----------------
>  Documentation/gpu/drm-uapi.rst        |   3 +
>  2 files changed, 107 insertions(+), 104 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
> index 0b302fedf1af..34f755bc9133 100644
> --- a/Documentation/gpu/drm-kms-helpers.rst
> +++ b/Documentation/gpu/drm-kms-helpers.rst
> @@ -2,38 +2,45 @@
>  Mode Setting Helper Functions
>  =============================
>
> -The plane, CRTC, encoder and connector functions provided by the drivers
> -implement the DRM API. They're called by the DRM core and ioctl handlers
> -to handle device state changes and configuration request. As
> -implementing those functions often requires logic not specific to
> -drivers, mid-layer helper functions are available to avoid duplicating
> -boilerplate code.
> -
> -The DRM core contains one mid-layer implementation. The mid-layer
> -provides implementations of several plane, CRTC, encoder and connector
> -functions (called from the top of the mid-layer) that pre-process
> -requests and call lower-level functions provided by the driver (at the
> -bottom of the mid-layer). For instance, the
> -:c:func:`drm_crtc_helper_set_config()` function can be used to
> -fill the :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>`
> -set_config field. When called, it will split the set_config operation
> -in smaller, simpler operations and call the driver to handle them.
> -
> -To use the mid-layer, drivers call
> -:c:func:`drm_crtc_helper_add()`,
> -:c:func:`drm_encoder_helper_add()` and
> -:c:func:`drm_connector_helper_add()` functions to install their
> -mid-layer bottom operations handlers, and fill the :c:type:`struct
> -drm_crtc_funcs <drm_crtc_funcs>`, :c:type:`struct
> -drm_encoder_funcs <drm_encoder_funcs>` and :c:type:`struct
> -drm_connector_funcs <drm_connector_funcs>` structures with
> -pointers to the mid-layer top API functions. Installing the mid-layer
> -bottom operation handlers is best done right after registering the
> -corresponding KMS object.
> -
> -The mid-layer is not split between CRTC, encoder and connector
> -operations. To use it, a driver must provide bottom functions for all of
> -the three KMS entities.
> +The DRM subsystem aims for a strong separation between core code and helper
> +libraries. Core code takes care of general setup and teardown and decoding
> +userspace requests to kernel internal objects. Everything else is handled by a
> +large set of helper libraries, which can be combined freely to pick and choose
> +for each driver what fits, and avoid shared code where special behaviour is
> +needed.
> +
> +This distinction between core code and helpers is especially strong in the
> +modesetting code, where there's a shared userspace ABI for all drivers. This is
> +in contrast to the render side, where pretty much everything (with very few
> +exceptions) can be considered optional helper code.
> +
> +There are a few areas these helpers can grouped into:
> +
> +* Helpers to implement modesetting. The important ones here are the atomic
> +  helpers. Old drivers still often use the legacy CRTC helpers. They both share
> +  the same set of common helper vtables. For really simple drivers (anything
> +  that would have been a great fit in the deprecated fbdev subsystem) there's
> +  also the simple display pipe helpers.
> +
> +* There's a big pile of helpers for handling outputs. First the generic bridge
> +  helpers for handling encoder and transcoder IP blocks. Second the panel helpers
> +  for handling panel-related information and logic. Plus then a big set of
> +  helpers for the various sink standards (DisplayPort, HDMI, MIPI DSI). Finally
> +  there's also generic helpers for handling output probing, and for dealing with
> +  EDIDs.
> +
> +* The last group of helpers concerns itself with the frontend side of a display
> +  pipeline: Planes, handling rectangles for visibility checking and scissoring,
> +  flip queues and assorted bits.
> +
> +Modeset Helper Reference for Common Vtables
> +===========================================
> +
> +.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
> +   :internal:
> +
> +.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
> +   :doc: overview
>
>  Atomic Modeset Helper Functions Reference
>  =========================================
> @@ -62,33 +69,27 @@ Atomic State Reset and Initialization
>  .. kernel-doc:: drivers/gpu/drm/drm_atomic_helper.c
>     :export:
>
> -Modeset Helper Reference for Common Vtables
> -===========================================
> -
> -.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
> -   :internal:
> -
> -.. kernel-doc:: include/drm/drm_modeset_helper_vtables.h
> -   :doc: overview
> -
>  Legacy CRTC/Modeset Helper Functions Reference
>  ==============================================
>
>  .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
> -   :export:
> +   :doc: overview
>
>  .. kernel-doc:: drivers/gpu/drm/drm_crtc_helper.c
> -   :doc: overview
> +   :export:
>
> -Output Probing Helper Functions Reference
> -=========================================
> +Simple KMS Helper Reference
> +===========================
>
> -.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
> -   :doc: output probing helper overview
> +.. kernel-doc:: include/drm/drm_simple_kms_helper.h
> +   :internal:
>
> -.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
> +.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
>     :export:
>
> +.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
> +   :doc: overview
> +
>  fbdev Helper Functions Reference
>  ================================
>
> @@ -110,6 +111,36 @@ Framebuffer CMA Helper Functions Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
>     :export:
>
> +Bridges
> +=======
> +
> +Overview
> +--------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> +   :doc: overview
> +
> +Default bridge callback sequence
> +--------------------------------
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> +   :doc: bridge callbacks
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> +   :export:
> +
> +Panel Helper Reference
> +======================
> +
> +.. kernel-doc:: include/drm/drm_panel.h
> +   :internal:
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_panel.c
> +   :export:
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_panel.c
> +   :doc: drm panel
> +
>  Display Port Helper Functions Reference
>  =======================================
>
> @@ -158,6 +189,15 @@ MIPI DSI Helper Functions Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_mipi_dsi.c
>     :export:
>
> +Output Probing Helper Functions Reference
> +=========================================
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
> +   :doc: output probing helper overview
> +
> +.. kernel-doc:: drivers/gpu/drm/drm_probe_helper.c
> +   :export:
> +
>  EDID Helper Functions Reference
>  ===============================
>
> @@ -176,18 +216,6 @@ Rectangle Utilities Reference
>  .. kernel-doc:: drivers/gpu/drm/drm_rect.c
>     :export:
>
> -Flip-work Helper Reference
> -==========================
> -
> -.. kernel-doc:: include/drm/drm_flip_work.h
> -   :doc: flip utils
> -
> -.. kernel-doc:: include/drm/drm_flip_work.h
> -   :internal:
> -
> -.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
> -   :export:
> -
>  HDMI Infoframes Helper Reference
>  ================================
>
> @@ -202,59 +230,31 @@ libraries and hence is also included here.
>  .. kernel-doc:: drivers/video/hdmi.c
>     :export:
>
> -Plane Helper Reference
> -======================
> -
> -.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
> -   :export:
> -
> -.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
> -   :doc: overview
> -
> -Tile group
> -----------
> -
> -.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
> -   :doc: Tile group
> -
> -Bridges
> -=======
> -
> -Overview
> ---------
> -
> -.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> -   :doc: overview
> +Flip-work Helper Reference
> +==========================
>
> -Default bridge callback sequence
> ---------------------------------
> +.. kernel-doc:: include/drm/drm_flip_work.h
> +   :doc: flip utils
>
> -.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> -   :doc: bridge callbacks
> +.. kernel-doc:: include/drm/drm_flip_work.h
> +   :internal:
>
> -.. kernel-doc:: drivers/gpu/drm/drm_bridge.c
> +.. kernel-doc:: drivers/gpu/drm/drm_flip_work.c
>     :export:
>
> -Panel Helper Reference
> +Plane Helper Reference
>  ======================
>
> -.. kernel-doc:: include/drm/drm_panel.h
> -   :internal:
> +.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
> +   :doc: overview
>
> -.. kernel-doc:: drivers/gpu/drm/drm_panel.c
> +.. kernel-doc:: drivers/gpu/drm/drm_plane_helper.c
>     :export:
>
> -.. kernel-doc:: drivers/gpu/drm/drm_panel.c
> -   :doc: drm panel
> -
> -Simple KMS Helper Reference
> -===========================
> -
> -.. kernel-doc:: include/drm/drm_simple_kms_helper.h
> -   :internal:
> +Tile group
> +==========
>
> -.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
> -   :export:
> +# FIXME: This should probably be moved into a property documentation section
>
> -.. kernel-doc:: drivers/gpu/drm/drm_simple_kms_helper.c
> -   :doc: overview
> +.. kernel-doc:: drivers/gpu/drm/drm_crtc.c
> +   :doc: Tile group
> diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
> index 536bf3eaadd4..94876938aef3 100644
> --- a/Documentation/gpu/drm-uapi.rst
> +++ b/Documentation/gpu/drm-uapi.rst
> @@ -33,6 +33,9 @@ Primary Nodes, DRM Master and Authentication
>  .. kernel-doc:: include/drm/drm_auth.h
>     :internal:
>
> +Open-Source Userspace Requirements
> +==================================
> +
>  Render nodes
>  ============
>
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings
  2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
                   ` (19 preceding siblings ...)
  2016-08-12 20:48 ` [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c Daniel Vetter
@ 2016-08-16 13:42 ` Sean Paul
  20 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-16 13:42 UTC (permalink / raw)
  To: Daniel Vetter
  Cc: Daniel Vetter, linux-doc, Markus Heiser, dri-devel, Jonathan Corbet


[-- Attachment #1.1: Type: text/plain, Size: 12528 bytes --]

On Aug 12, 2016 1:49 PM, "Daniel Vetter" <daniel.vetter@ffwll.ch> wrote:
>
> These are the leftovers I could only track down using keep_warnings =
> True. For some of them we might want to update our style guide on how
> to reference structures and constants, not sure ...
>
> Cc: Markus Heiser <markus.heiser@darmarit.de>
> Cc: Jonathan Corbet <corbet@lwn.net>
> Cc: linux-doc@vger.kernel.org
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  drivers/gpu/drm/drm_crtc.c              |  4 ++--
>  drivers/gpu/drm/drm_fb_helper.c         |  2 +-
>  drivers/gpu/drm/drm_irq.c               |  8 +++----
>  drivers/gpu/drm/drm_simple_kms_helper.c |  2 +-
>  drivers/gpu/drm/i915/i915_vgpu.c        | 42
++++++++++++++++-----------------
>  drivers/gpu/drm/i915/intel_audio.c      |  6 ++---
>  drivers/gpu/drm/i915/intel_guc_fwif.h   |  5 ++--
>  include/drm/drm_crtc.h                  |  8 +++----
>  include/drm/drm_gem.h                   |  4 ++--
>  9 files changed, 41 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index c31298f0bb0e..4cb8f4b49d8b 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1272,7 +1272,7 @@ static unsigned int drm_num_planes(struct
drm_device *dev)
>   * @plane: plane object to init
>   * @possible_crtcs: bitmask of possible CRTCs
>   * @funcs: callbacks for the new plane
> - * @formats: array of supported formats (%DRM_FORMAT_*)
> + * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
>   * @type: type of plane (overlay, primary, cursor)
>   * @name: printf style format string for the plane name, or NULL for
default name
> @@ -1387,7 +1387,7 @@ static void drm_plane_unregister_all(struct
drm_device *dev)
>   * @plane: plane object to init
>   * @possible_crtcs: bitmask of possible CRTCs
>   * @funcs: callbacks for the new plane
> - * @formats: array of supported formats (%DRM_FORMAT_*)
> + * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
>   * @is_primary: plane type (primary vs overlay)
>   *
> diff --git a/drivers/gpu/drm/drm_fb_helper.c
b/drivers/gpu/drm/drm_fb_helper.c
> index aed79d31930c..c0d1066ea419 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2193,7 +2193,7 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config);
>   * @fb_helper: the drm_fb_helper
>   *
>   * Scan the connectors attached to the fb_helper and try to put together
a
> - * setup after *notification of a change in output configuration.
> + * setup after notification of a change in output configuration.
>   *
>   * Called at runtime, takes the mode config locks to be able to
check/change the
>   * modeset configuration. Must be run from process context (which
usually means
> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> index 9bdce1cb6c5c..10611a936059 100644
> --- a/drivers/gpu/drm/drm_irq.c
> +++ b/drivers/gpu/drm/drm_irq.c
> @@ -713,10 +713,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
>   * Negative value on error, failure or if not supported in current
>   * video mode:
>   *
> - * -EINVAL   - Invalid CRTC.
> - * -EAGAIN   - Temporary unavailable, e.g., called before initial
modeset.
> - * -ENOTSUPP - Function not supported in current display mode.
> - * -EIO      - Failed, e.g., due to failed scanout position query.
> + * -EINVAL    Invalid CRTC.
> + * -EAGAIN    Temporary unavailable, e.g., called before initial modeset.
> + * -ENOTSUPP  Function not supported in current display mode.
> + * -EIO       Failed, e.g., due to failed scanout position query.
>   *
>   * Returns or'ed positive status flags on success:
>   *
> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c
b/drivers/gpu/drm/drm_simple_kms_helper.c
> index 0a02efe978ee..bada17166512 100644
> --- a/drivers/gpu/drm/drm_simple_kms_helper.c
> +++ b/drivers/gpu/drm/drm_simple_kms_helper.c
> @@ -137,7 +137,7 @@ static const struct drm_plane_funcs
drm_simple_kms_plane_funcs = {
>   * @dev: DRM device
>   * @pipe: simple display pipe object to initialize
>   * @funcs: callbacks for the display pipe (optional)
> - * @formats: array of supported formats (%DRM_FORMAT_*)
> + * @formats: array of supported formats (DRM_FORMAT\_\*)
>   * @format_count: number of elements in @formats
>   * @connector: connector to attach and register
>   *
> diff --git a/drivers/gpu/drm/i915/i915_vgpu.c
b/drivers/gpu/drm/i915/i915_vgpu.c
> index 142bac976919..ca2e91259948 100644
> --- a/drivers/gpu/drm/i915/i915_vgpu.c
> +++ b/drivers/gpu/drm/i915/i915_vgpu.c
> @@ -156,27 +156,27 @@ static int vgt_balloon_space(struct drm_mm *mm,
>   * host point of view, the graphic address space is partitioned by
multiple
>   * vGPUs in different VMs. ::
>   *
> - *                        vGPU1 view         Host view
> - *             0 ------> +-----------+     +-----------+
> - *               ^       |###########|     |   vGPU3   |
> - *               |       |###########|     +-----------+
> - *               |       |###########|     |   vGPU2   |
> - *               |       +-----------+     +-----------+
> - *        mappable GM    | available | ==> |   vGPU1   |
> - *               |       +-----------+     +-----------+
> - *               |       |###########|     |           |
> - *               v       |###########|     |   Host    |
> - *               +=======+===========+     +===========+
> - *               ^       |###########|     |   vGPU3   |
> - *               |       |###########|     +-----------+
> - *               |       |###########|     |   vGPU2   |
> - *               |       +-----------+     +-----------+
> - *      unmappable GM    | available | ==> |   vGPU1   |
> - *               |       +-----------+     +-----------+
> - *               |       |###########|     |           |
> - *               |       |###########|     |   Host    |
> - *               v       |###########|     |           |
> - * total GM size ------> +-----------+     +-----------+
> + *                         vGPU1 view         Host view
> + *              0 ------> +-----------+     +-----------+
> + *                ^       |###########|     |   vGPU3   |
> + *                |       |###########|     +-----------+
> + *                |       |###########|     |   vGPU2   |
> + *                |       +-----------+     +-----------+
> + *         mappable GM    | available | ==> |   vGPU1   |
> + *                |       +-----------+     +-----------+
> + *                |       |###########|     |           |
> + *                v       |###########|     |   Host    |
> + *                +=======+===========+     +===========+
> + *                ^       |###########|     |   vGPU3   |
> + *                |       |###########|     +-----------+
> + *                |       |###########|     |   vGPU2   |
> + *                |       +-----------+     +-----------+
> + *       unmappable GM    | available | ==> |   vGPU1   |
> + *                |       +-----------+     +-----------+
> + *                |       |###########|     |           |
> + *                |       |###########|     |   Host    |
> + *                v       |###########|     |           |
> + *  total GM size ------> +-----------+     +-----------+
>   *
>   * Returns:
>   * zero on success, non-zero if configuration invalid or ballooning
failed
> diff --git a/drivers/gpu/drm/i915/intel_audio.c
b/drivers/gpu/drm/i915/intel_audio.c
> index d32f586f9c05..85389cdd0bec 100644
> --- a/drivers/gpu/drm/i915/intel_audio.c
> +++ b/drivers/gpu/drm/i915/intel_audio.c
> @@ -51,10 +51,10 @@
>   * related registers. (The notable exception is the power management, not
>   * covered here.)
>   *
> - * The struct i915_audio_component is used to interact between the
graphics
> - * and audio drivers. The struct i915_audio_component_ops *ops in it is
> + * The struct &i915_audio_component is used to interact between the
graphics
> + * and audio drivers. The struct &i915_audio_component_ops @ops in it is
>   * defined in graphics driver and called in audio driver. The
> - * struct i915_audio_component_audio_ops *audio_ops is called from i915
driver.
> + * struct &i915_audio_component_audio_ops @audio_ops is called from i915
driver.
>   */
>
>  static const struct {
> diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h
b/drivers/gpu/drm/i915/intel_guc_fwif.h
> index 944786d7075b..e40db2d2ae99 100644
> --- a/drivers/gpu/drm/i915/intel_guc_fwif.h
> +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
> @@ -155,6 +155,7 @@
>   *
>   *     +-------------------------------+
>   *     |        guc_css_header         |
> + *     |                               |
>   *     | contains major/minor version  |
>   *     +-------------------------------+
>   *     |             uCode             |
> @@ -176,10 +177,10 @@
>   *
>   * 1. Header, uCode and RSA are must-have components.
>   * 2. All firmware components, if they present, are in the sequence
illustrated
> - * in the layout table above.
> + *    in the layout table above.
>   * 3. Length info of each component can be found in header, in dwords.
>   * 4. Modulus and exponent key are not required by driver. They may not
appear
> - * in fw. So driver will load a truncated firmware in this case.
> + *    in fw. So driver will load a truncated firmware in this case.
>   */
>
>  struct guc_css_header {
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index b618b506b04d..194eebb2f9d7 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1197,7 +1197,7 @@ struct drm_encoder_funcs {
>   * @head: list management
>   * @base: base KMS object
>   * @name: human readable name, can be overwritten by the driver
> - * @encoder_type: one of the %DRM_MODE_ENCODER_<foo> types in drm_mode.h
> + * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
>   * @possible_crtcs: bitmask of potential CRTC bindings
>   * @possible_clones: bitmask of potential sibling encoders for cloning
>   * @crtc: currently bound CRTC
> @@ -1250,7 +1250,7 @@ struct drm_encoder {
>   * @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: 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?
> @@ -1263,11 +1263,11 @@ struct drm_encoder {
>   * @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
> + * @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
> + * @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
> diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> index fca1cd1b9c26..9f63736e6163 100644
> --- a/include/drm/drm_gem.h
> +++ b/include/drm/drm_gem.h
> @@ -210,8 +210,8 @@ drm_gem_object_reference(struct drm_gem_object *obj)
>   * drm_gem_object_unreference_unlocked().
>   *
>   * Drivers should never call this directly in their code. Instead they
should
> - * wrap it up into a driver_gem_object_unreference(struct
driver_gem_object
> - * *obj) wrapper function, and use that. Shared code should never call
this, to
> + * wrap it up into a ``driver_gem_object_unreference(struct
driver_gem_object
> + * *obj)`` wrapper function, and use that. Shared code should never call
this, to
>   * avoid breaking drivers by accident which still depend upon
dev->struct_mutex
>   * locking.
>   */
> --
> 2.8.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

[-- Attachment #1.2: Type: text/html, Size: 15939 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 12/21] drm/doc: Update drm_framebuffer docs
  2016-08-12 20:48 ` [PATCH 12/21] drm/doc: Update drm_framebuffer docs Daniel Vetter
@ 2016-08-16 16:11   ` Sean Paul
  0 siblings, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-08-16 16:11 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 1:48 PM, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> - Move the intro section into a DOC comment, and update it slightly.
> - kernel-doc for struct drm_framebuffer!
>
> v2:
> - Copypaste fail (Sean).
> - Explain the linear @offsets clearer (Ville).
>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> ---
>  Documentation/gpu/drm-kms.rst     |  26 +---------
>  drivers/gpu/drm/drm_framebuffer.c |  35 +++++++++++++
>  include/drm/drm_framebuffer.h     | 106 +++++++++++++++++++++++++++++++++-----
>  3 files changed, 130 insertions(+), 37 deletions(-)
>
> diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst
> index 8264a88a8695..d244e03658cc 100644
> --- a/Documentation/gpu/drm-kms.rst
> +++ b/Documentation/gpu/drm-kms.rst
> @@ -39,30 +39,8 @@ Atomic Mode Setting Function Reference
>  Frame Buffer Abstraction
>  ========================
>
> -Frame buffers are abstract memory objects that provide a source of
> -pixels to scanout to a CRTC. Applications explicitly request the
> -creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls
> -and receive an opaque handle that can be passed to the KMS CRTC control,
> -plane configuration and page flip functions.
> -
> -Frame buffers rely on the underneath memory manager for low-level memory
> -operations. When creating a frame buffer applications pass a memory
> -handle (or a list of memory handles for multi-planar formats) through
> -the ``drm_mode_fb_cmd2`` argument. For drivers using GEM as their
> -userspace buffer management interface this would be a GEM handle.
> -Drivers are however free to use their own backing storage object
> -handles, e.g. vmwgfx directly exposes special TTM handles to userspace
> -and so expects TTM handles in the create ioctl and not GEM handles.
> -
> -The lifetime of a drm framebuffer is controlled with a reference count,
> -drivers can grab additional references with
> -:c:func:`drm_framebuffer_reference()`and drop them again with
> -:c:func:`drm_framebuffer_unreference()`. For driver-private
> -framebuffers for which the last reference is never dropped (e.g. for the
> -fbdev framebuffer when the struct :c:type:`struct drm_framebuffer
> -<drm_framebuffer>` is embedded into the fbdev helper struct)
> -drivers can manually clean up a framebuffer at module unload time with
> -:c:func:`drm_framebuffer_unregister_private()`.
> +.. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c
> +   :doc: overview
>
>  Frame Buffer Functions Reference
>  --------------------------------
> diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
> index 19478a25ac20..34e3c4acbc8a 100644
> --- a/drivers/gpu/drm/drm_framebuffer.c
> +++ b/drivers/gpu/drm/drm_framebuffer.c
> @@ -28,6 +28,41 @@
>  #include "drm_crtc_internal.h"
>
>  /**
> + * DOC: overview
> + *
> + * Frame buffers are abstract memory objects that provide a source of pixels to
> + * scanout to a CRTC. Applications explicitly request the creation of frame
> + * buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and receive an opaque
> + * handle that can be passed to the KMS CRTC control, plane configuration and
> + * page flip functions.
> + *
> + * Frame buffers rely on the underlying memory manager for allocating backing
> + * storage. When creating a frame buffer applications pass a memory handle
> + * (or a list of memory handles for multi-planar formats) through the
> + * struct &drm_mode_fb_cmd2 argument. For drivers using GEM as their userspace
> + * buffer management interface this would be a GEM handle.  Drivers are however
> + * free to use their own backing storage object handles, e.g. vmwgfx directly
> + * exposes special TTM handles to userspace and so expects TTM handles in the
> + * create ioctl and not GEM handles.
> + *
> + * Framebuffers are tracked with struct &drm_framebuffer. They are published
> + * using drm_framebuffer_init() - after calling that function userspace can use
> + * and access the framebuffer object. The helper function
> + * drm_helper_mode_fill_fb_struct() can be used to pre-fill the required
> + * metadata fields.
> + *
> + * The lifetime of a drm framebuffer is controlled with a reference count,
> + * drivers can grab additional references with drm_framebuffer_reference() and
> + * drop them again with drm_framebuffer_unreference(). For driver-private
> + * framebuffers for which the last reference is never dropped (e.g. for the
> + * fbdev framebuffer when the struct struct &drm_framebuffer is embedded into
> + * the fbdev helper struct) drivers can manually clean up a framebuffer at
> + * module unload time with drm_framebuffer_unregister_private(). But doing this
> + * is not recommended, and it's better to have a normal free-standing struct
> + * &drm_framebuffer.
> + */
> +
> +/**
>   * drm_mode_addfb - add an FB to the graphics configuration
>   * @dev: drm device for the ioctl
>   * @data: data pointer for the ioctl
> diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
> index 46abdace8fa5..50deb40d3bfd 100644
> --- a/include/drm/drm_framebuffer.h
> +++ b/include/drm/drm_framebuffer.h
> @@ -92,37 +92,117 @@ struct drm_framebuffer_funcs {
>                      unsigned num_clips);
>  };
>
> +/**
> + * struct drm_framebuffer - frame buffer object
> + *
> + * Note that the fb is refcounted for the benefit of driver internals,
> + * for example some hw, disabling a CRTC/plane is asynchronous, and
> + * scanout does not actually complete until the next vblank.  So some
> + * cleanup (like releasing the reference(s) on the backing GEM bo(s))
> + * should be deferred.  In cases like this, the driver would like to
> + * hold a ref to the fb even though it has already been removed from
> + * userspace perspective. See drm_framebuffer_reference() and
> + * drm_framebuffer_unreference().
> + *
> + * The refcount is stored inside the mode object @base.
> + */
>  struct drm_framebuffer {
> +       /**
> +        * @dev: DRM device this framebuffer belongs to
> +        */
>         struct drm_device *dev;
> -       /*
> -        * Note that the fb is refcounted for the benefit of driver internals,
> -        * for example some hw, disabling a CRTC/plane is asynchronous, and
> -        * scanout does not actually complete until the next vblank.  So some
> -        * cleanup (like releasing the reference(s) on the backing GEM bo(s))
> -        * should be deferred.  In cases like this, the driver would like to
> -        * hold a ref to the fb even though it has already been removed from
> -        * userspace perspective.
> -        * The refcount is stored inside the mode object.
> -        */
> -       /*
> -        * Place on the dev->mode_config.fb_list, access protected by
> +       /**
> +        * @head: Place on the dev->mode_config.fb_list, access protected by
>          * dev->mode_config.fb_lock.
>          */
>         struct list_head head;
> +
> +       /**
> +        * @base: base modeset object structure, contains the reference count.
> +        */
>         struct drm_mode_object base;
> +       /**
> +        * @funcs: framebuffer vfunc table
> +        */
>         const struct drm_framebuffer_funcs *funcs;
> +       /**
> +        * @pitches: Line stride per buffer. For userspace created object this
> +        * is copied from drm_mode_fb_cmd2.
> +        */
>         unsigned int pitches[4];
> +       /**
> +        * @offsets: Offset from buffer start to the actual pixel data in bytes,
> +        * per buffer. For userspace created object this is copied from
> +        * drm_mode_fb_cmd2.
> +        *
> +        * Note that this is a linear offset and does not take into account
> +        * tiling or buffer laytou per @modifier. It meant to be used when the
> +        * actual pixel data for this framebuffer plane starts at an offset,
> +        * e.g.  when multiple planes are allocated within the same backing
> +        * storage buffer object. For tiled layouts this generally means it
> +        * @offsets must at least be tile-size aligned, but hardware often has
> +        * stricter requirements.
> +        *
> +        * This should not be used to specifiy x/y pixel offsets into the buffer
> +        * data (even for linear buffers). Specifying an x/y pixel offset is
> +        * instead done through the source rectangle in struct &drm_plane_state.
> +        */
>         unsigned int offsets[4];
> +       /**
> +        * @modifier: Data layout modifier, per buffer. This is used to describe
> +        * tiling, or also special layouts (like compression) of auxiliary
> +        * buffers. For userspace created object this is copied from
> +        * drm_mode_fb_cmd2.
> +        */
>         uint64_t modifier[4];
> +       /**
> +        * @width: Logical width of the visible area of the framebuffer, in
> +        * pixels.
> +        */
>         unsigned int width;
> +       /**
> +        * @height: Logical height of the visible area of the framebuffer, in
> +        * pixels.
> +        */
>         unsigned int height;
> -       /* depth can be 15 or 16 */
> +       /**
> +        * @depth: Depth in bits per pixel for RGB formats. 0 for everything
> +        * else. Legacy information derived from @pixel_format, it's suggested to use
> +        * the DRM FOURCC codes and helper functions directly instead.
> +        */
>         unsigned int depth;
> +       /**
> +        * @bits_per_pixel: Storage used bits per pixel for RGB formats. 0 for
> +        * everything else. Legacy information derived from @pixel_format, it's
> +        * suggested to use the DRM FOURCC codes and helper functions directly
> +        * instead.
> +        */
>         int bits_per_pixel;
> +       /**
> +        * @flags: Framebuffer flags like DRM_MODE_FB_INTERLACED or
> +        * DRM_MODE_FB_MODIFIERS.
> +        */
>         int flags;
> +       /**
> +        * @pixel_format: DRM FOURCC code describing the pixel format.
> +        */
>         uint32_t pixel_format; /* fourcc format */
> +       /**
> +        * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor
> +        * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
> +        * universal plane.
> +        */
>         int hot_x;
> +       /**
> +        * @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor
> +        * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR
> +        * universal plane.
> +        */
>         int hot_y;
> +       /**
> +        * @filp_head: Placed on struct &drm_file fbs list_head, protected by
> +        * fbs_lock in the same structure.
> +        */
>         struct list_head filp_head;
>  };
>
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/21] drm/hisilicon: Don't set drm_device->platformdev
  2016-08-12 20:48 ` [PATCH 07/21] drm/hisilicon: " Daniel Vetter
@ 2016-08-17  3:19   ` Xinliang Liu
  0 siblings, 0 replies; 36+ messages in thread
From: Xinliang Liu @ 2016-08-17  3:19 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On 13 August 2016 at 04:48, Daniel Vetter <daniel.vetter@ffwll.ch> wrote:
> It's deprecated and only should be used by drivers which still use
> drm_platform_init, not by anyone else.
>
> And indeed it's entirely unused and can be nuked.
>
> This required a bit more fudging, but I guess kirin_dc_ops really
> wants to operate on the platform_device, not something else. Also
> bonus points for implementing abstraction, and then storing the vfunc
> in a global variable.
>
> Cc: Xinliang Liu <xinliang.liu@linaro.org>
> Cc: Xinwei Kong <kong.kongxinwei@hisilicon.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Reviewed-by: Sean Paul <seanpaul@chromium.org>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Reviewed-by: Xinliang Liu <xinliang.liu@linaro.org>

Thanks,
-xinliang

> ---
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 10 +++++-----
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c |  6 ++----
>  drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h |  4 ++--
>  3 files changed, 9 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> index c3707d47cd89..34c22823e5c2 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c
> @@ -987,9 +987,9 @@ static int ade_dts_parse(struct platform_device *pdev, struct ade_hw_ctx *ctx)
>         return 0;
>  }
>
> -static int ade_drm_init(struct drm_device *dev)
> +static int ade_drm_init(struct platform_device *pdev)
>  {
> -       struct platform_device *pdev = dev->platformdev;
> +       struct drm_device *drm_dev = platform_get_drvdata(dev);
>         struct ade_data *ade;
>         struct ade_hw_ctx *ctx;
>         struct ade_crtc *acrtc;
> @@ -1048,9 +1048,9 @@ static int ade_drm_init(struct drm_device *dev)
>         return 0;
>  }
>
> -static void ade_drm_cleanup(struct drm_device *dev)
> +static void ade_drm_cleanup(struct platform_device *pdev)
>  {
> -       struct platform_device *pdev = dev->platformdev;
> +       struct drm_device *drm_dev = platform_get_drvdata(dev);
>         struct ade_data *ade = platform_get_drvdata(pdev);
>         struct drm_crtc *crtc = &ade->acrtc.base;
>
> @@ -1060,4 +1060,4 @@ static void ade_drm_cleanup(struct drm_device *dev)
>  const struct kirin_dc_ops ade_dc_ops = {
>         .init = ade_drm_init,
>         .cleanup = ade_drm_cleanup
> -};
> +;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> index 1edd9bc80294..a31016af9b61 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
> @@ -41,7 +41,7 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev)
>  #endif
>         drm_kms_helper_poll_fini(dev);
>         drm_vblank_cleanup(dev);
> -       dc_ops->cleanup(dev);
> +       dc_ops->cleanup(to_platform_device(dev->dev));
>         drm_mode_config_cleanup(dev);
>         devm_kfree(dev->dev, priv);
>         dev->dev_private = NULL;
> @@ -103,7 +103,7 @@ static int kirin_drm_kms_init(struct drm_device *dev)
>         kirin_drm_mode_config_init(dev);
>
>         /* display controller init */
> -       ret = dc_ops->init(dev);
> +       ret = dc_ops->init(to_platform_device(dev));
>         if (ret)
>                 goto err_mode_config_cleanup;
>
> @@ -210,8 +210,6 @@ static int kirin_drm_bind(struct device *dev)
>         if (!drm_dev)
>                 return -ENOMEM;
>
> -       drm_dev->platformdev = to_platform_device(dev);
> -
>         ret = kirin_drm_kms_init(drm_dev);
>         if (ret)
>                 goto err_drm_dev_unref;
> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
> index 1a07caf8e7f4..a0bb217c4c64 100644
> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h
> @@ -15,8 +15,8 @@
>
>  /* display controller init/cleanup ops */
>  struct kirin_dc_ops {
> -       int (*init)(struct drm_device *dev);
> -       void (*cleanup)(struct drm_device *dev);
> +       int (*init)(struct platform_device *pdev);
> +       void (*cleanup)(struct platform_device *pdev);
>  };
>
>  struct kirin_drm_private {
> --
> 2.8.1
>
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 14/21] drm: Extract drm_connector.[hc]
  2016-08-12 20:48 ` [PATCH 14/21] drm: Extract drm_connector.[hc] Daniel Vetter
  2016-08-15 20:15   ` Sean Paul
@ 2016-09-21 14:29   ` Sean Paul
  1 sibling, 0 replies; 36+ messages in thread
From: Sean Paul @ 2016-09-21 14:29 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development

On Fri, Aug 12, 2016 at 10:48:50PM +0200, Daniel Vetter 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.
> 
> 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
> 

<snip>

> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index f4d041800551..e30ea0be6417 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h


<snip>

> -
> -#define MAX_ELD_BYTES	128
> -

Building drm-misc-arm gives:

../sound/soc/codecs/hdmi-codec.c:34:14: error: ‘MAX_ELD_BYTES’ undeclared here
(not in a function)
make[4]: *** [sound/soc/codecs/hdmi-codec.o] Error 1
make[3]: *** [sound/soc/codecs] Error 2
make[2]: *** [sound/soc] Error 2
make[2]: *** Waiting for unfinished jobs....



From hdmi-codec.c:

#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */


I can post a patch tomorrow morning if no one gets to it before then.

Sean
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2016-09-21 14:29 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-12 20:48 [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Daniel Vetter
2016-08-12 20:48 ` [PATCH 02/21] drm/doc: Light drm-kms-helper.rst cleanup Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 03/21] drm/kms-helpers: Extract drm_modeset_helper.[hc] Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 04/21] drm/doc: Reorg drm-mm.rst Daniel Vetter
2016-08-12 20:48 ` [PATCH 05/21] drm/doc: Reorg for drm-kms.rst Daniel Vetter
2016-08-12 20:48 ` [PATCH 06/21] drm/etnaviv: Don't set drm_device->platformdev Daniel Vetter
2016-08-15  9:07   ` Lucas Stach
2016-08-12 20:48 ` [PATCH 07/21] drm/hisilicon: " Daniel Vetter
2016-08-17  3:19   ` Xinliang Liu
2016-08-12 20:48 ` [PATCH 08/21] drm/doc: Remove outdated FIXME for the page_flip callback Daniel Vetter
2016-08-12 20:48 ` [PATCH 09/21] drm/kms: Nuke dirty_info property Daniel Vetter
2016-08-12 20:48 ` [PATCH 10/21] drm/doc: Include drm_atomic.h Daniel Vetter
2016-08-12 20:48 ` [PATCH 11/21] drm: Extract drm_framebuffer.[hc] Daniel Vetter
2016-08-15 14:07   ` [PATCH] " Daniel Vetter
2016-08-15 20:15     ` Sean Paul
2016-08-12 20:48 ` [PATCH 12/21] drm/doc: Update drm_framebuffer docs Daniel Vetter
2016-08-16 16:11   ` Sean Paul
2016-08-12 20:48 ` [PATCH 13/21] drm: Export drm_property_replace_global_blob Daniel Vetter
2016-08-12 20:48 ` [PATCH 14/21] drm: Extract drm_connector.[hc] Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-09-21 14:29   ` Sean Paul
2016-08-12 20:48 ` [PATCH 15/21] drm/doc: Include new drm_blend.c Daniel Vetter
2016-08-12 20:48 ` [PATCH 16/21] drm: Don't export dp-aux devnode functions Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 17/21] drm: Update connector documentation Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 18/21] drm: Remove display_info->min/max_(h|v)max Daniel Vetter
2016-08-12 20:48 ` [PATCH 19/21] drm: document drm_display_info Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 20/21] vgaarbiter: rst-ifiy and polish kerneldoc Daniel Vetter
2016-08-15 20:15   ` Sean Paul
2016-08-12 20:48 ` [PATCH 21/21] drm: Fix kerneldoc in drm_plane_helper.c Daniel Vetter
2016-08-15 20:14   ` Sean Paul
2016-08-16 13:42 ` [PATCH 01/21] drm/doc: Fix more kerneldoc/sphinx warnings Sean Paul

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.