Merge tag 'topic/drm-misc-2016-09-25' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Wed, 28 Sep 2016 00:28:23 +0000 (10:28 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 28 Sep 2016 00:28:23 +0000 (10:28 +1000)
- more core cleanup patches to prep drm_file to be used for
  kernel-internal contexts (David Herrmann)
- more split-up+docs for drm_crtc.c
- lots of small fixes and polish all over

* tag 'topic/drm-misc-2016-09-25' of git://anongit.freedesktop.org/drm-intel: (37 commits)
  drm: bridge: analogix/dp: mark symbols static where possible
  drm/bochs: mark bochs_connector_get_modes() static
  drm/bridge: analogix_dp: Improve panel on time
  drm/bridge: analogix_dp: Don't read EDID if panel present
  drm/bridge: analogix_dp: Remove duplicated code
  Revert "drm/i2c: tda998x: don't register the connector"
  drm: Fix plane type uabi breakage
  dma-buf/sync_file: free fences array in num_fences is 1
  drm/i2c: tda998x: don't register the connector
  drm: Don't swallow error codes in drm_dev_alloc()
  drm: Distinguish no name from ENOMEM in set_unique()
  drm: Remove dirty property from docs
  drm/doc: Document color space handling
  drm: Extract drm_color_mgmt.[hc]
  drm/doc: Polish plane composition property docs
  drm: Conslidate blending properties in drm_blend.[hc]
  drm/doc: Polish for drm_plane.[hc]
  drm: Extract drm_plane.[hc]
  drm/tilcdc: Add atomic and crtc headers to crtc.c
  drm: Fix typo in encoder docs
  ...

79 files changed:
Documentation/gpu/drm-kms-helpers.rst
Documentation/gpu/drm-kms.rst
Documentation/gpu/kms-properties.csv
drivers/dma-buf/sync_file.c
drivers/gpu/drm/Makefile
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/arc/arcpgu_drv.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/arm/malidp_drv.c
drivers/gpu/drm/ast/ast_ttm.c
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
drivers/gpu/drm/bochs/bochs_kms.c
drivers/gpu/drm/bochs/bochs_mm.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
drivers/gpu/drm/cirrus/cirrus_ttm.c
drivers/gpu/drm/drm_atomic_helper.c
drivers/gpu/drm/drm_blend.c
drivers/gpu/drm/drm_bridge.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_color_mgmt.c [new file with mode: 0644]
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper_internal.h
drivers/gpu/drm/drm_crtc_internal.h
drivers/gpu/drm/drm_dp_helper.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_encoder.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_framebuffer.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_plane.c [new file with mode: 0644]
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/drm_sysfs.c
drivers/gpu/drm/drm_vma_manager.c
drivers/gpu/drm/etnaviv/etnaviv_drv.c
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
drivers/gpu/drm/mediatek/mtk_drm_drv.c
drivers/gpu/drm/mgag200/mgag200_ttm.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/qxl/qxl_ttm.c
drivers/gpu/drm/radeon/radeon_ttm.c
drivers/gpu/drm/rcar-du/rcar_du_drv.c
drivers/gpu/drm/rockchip/rockchip_drm_drv.c
drivers/gpu/drm/sti/sti_drv.c
drivers/gpu/drm/sun4i/sun4i_drv.c
drivers/gpu/drm/tegra/drm.c
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/vc4/vc4_drv.c
drivers/gpu/drm/vgem/vgem_drv.c
drivers/gpu/drm/virtio/virtgpu_drm_bus.c
include/drm/drmP.h
include/drm/drm_atomic.h
include/drm/drm_blend.h [new file with mode: 0644]
include/drm/drm_bridge.h [new file with mode: 0644]
include/drm/drm_color_mgmt.h [new file with mode: 0644]
include/drm/drm_connector.h
include/drm/drm_core.h [deleted file]
include/drm/drm_crtc.h
include/drm/drm_edid.h
include/drm/drm_encoder.h
include/drm/drm_fb_helper.h
include/drm/drm_framebuffer.h
include/drm/drm_mode_object.h
include/drm/drm_modes.h
include/drm/drm_plane.h [new file with mode: 0644]
include/drm/drm_property.h
include/drm/drm_vma_manager.h
include/uapi/linux/sync_file.h

index 59fa3c11efabd38ad05b45e0965f0460a8bbeee1..bb4254d19cbb810c038922dac9dd7997cff02ea9 100644 (file)
@@ -126,6 +126,13 @@ Default bridge callback sequence
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
    :doc: bridge callbacks
 
+
+Bridge Helper Reference
+-------------------------
+
+.. kernel-doc:: include/drm/drm_bridge.h
+   :internal:
+
 .. kernel-doc:: drivers/gpu/drm/drm_bridge.c
    :export:
 
@@ -201,6 +208,9 @@ Output Probing Helper Functions Reference
 EDID Helper Functions Reference
 ===============================
 
+.. kernel-doc:: include/drm/drm_edid.h
+   :internal:
+
 .. kernel-doc:: drivers/gpu/drm/drm_edid.c
    :export:
 
index f9a991bb87d4cf5a8ab7c370b289ffe10a8ffbc8..53b872c105d24f0741e06f463ab2fdadbb0c01cd 100644 (file)
@@ -110,6 +110,21 @@ 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.
 
+Plane Abstraction
+=================
+
+.. kernel-doc:: drivers/gpu/drm/drm_plane.c
+   :doc: overview
+
+Plane Functions Reference
+-------------------------
+
+.. kernel-doc:: include/drm/drm_plane.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_plane.c
+   :export:
+
 Display Modes Function Reference
 ================================
 
@@ -177,50 +192,6 @@ allocated and zeroed by the driver, possibly as part of a larger
 structure, and registered with a call to :c:func:`drm_crtc_init()`
 with a pointer to CRTC functions.
 
-Planes (:c:type:`struct drm_plane <drm_plane>`)
------------------------------------------------
-
-A plane represents an image source that can be blended with or overlayed
-on top of a CRTC during the scanout process. Planes are associated with
-a frame buffer to crop a portion of the image memory (source) and
-optionally scale it to a destination size. The result is then blended
-with or overlayed on top of a CRTC.
-
-The DRM core recognizes three types of planes:
-
--  DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC.
-   Primary planes are the planes operated upon by CRTC modesetting and
-   flipping operations described in the page_flip hook in
-   :c:type:`struct drm_crtc_funcs <drm_crtc_funcs>`.
--  DRM_PLANE_TYPE_CURSOR represents a "cursor" plane for a CRTC.
-   Cursor planes are the planes operated upon by the
-   DRM_IOCTL_MODE_CURSOR and DRM_IOCTL_MODE_CURSOR2 ioctls.
--  DRM_PLANE_TYPE_OVERLAY represents all non-primary, non-cursor
-   planes. Some drivers refer to these types of planes as "sprites"
-   internally.
-
-For compatibility with legacy userspace, only overlay planes are made
-available to userspace by default. Userspace clients may set the
-DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate
-that they wish to receive a universal plane list containing all plane
-types.
-
-Plane Initialization
-~~~~~~~~~~~~~~~~~~~~
-
-To create a plane, a KMS drivers allocates and zeroes an instances of
-:c:type:`struct drm_plane <drm_plane>` (possibly as part of a
-larger structure) and registers it with a call to
-:c:func:`drm_universal_plane_init()`. The function takes a
-bitmask of the CRTCs that can be associated with the plane, a pointer to
-the plane functions, a list of format supported formats, and the type of
-plane (primary, cursor, or overlay) being initialized.
-
-Cursor and overlay planes are optional. All drivers should provide one
-primary plane per CRTC (although this requirement may change in the
-future); drivers that do not wish to provide special handling for
-primary planes may make use of the helper functions described in ? to
-create and register a primary plane with standard capabilities.
 
 Cleanup
 -------
@@ -316,12 +287,27 @@ Property Types and Blob Property Support
 .. kernel-doc:: drivers/gpu/drm/drm_property.c
    :export:
 
-Blending and Z-Position properties
-----------------------------------
+Plane Composition Properties
+----------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_blend.c
+   :doc: overview
 
 .. kernel-doc:: drivers/gpu/drm/drm_blend.c
    :export:
 
+Color Management Properties
+---------------------------
+
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
+   :doc: overview
+
+.. kernel-doc:: include/drm/drm_color_mgmt.h
+   :internal:
+
+.. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c
+   :export:
+
 Existing KMS Properties
 -----------------------
 
index 4c5ce3edcfd9250978865c2a2b10f7d8538770df..981873a05d14845a334ef767e5de6673132dac09 100644 (file)
@@ -1,23 +1,10 @@
 Owner Module/Drivers,Group,Property Name,Type,Property Values,Object attached,Description/Restrictions
-DRM,Generic,“rotation”,BITMASK,"{ 0, ""rotate-0"" }, { 1, ""rotate-90"" }, { 2, ""rotate-180"" }, { 3, ""rotate-270"" }, { 4, ""reflect-x"" }, { 5, ""reflect-y"" }","CRTC, Plane",rotate-(degrees) rotates the image by the specified amount in degrees in counter clockwise direction. reflect-x and reflect-y reflects the image along the specified axis prior to rotation
 ,,“scaling mode”,ENUM,"{ ""None"", ""Full"", ""Center"", ""Full aspect"" }",Connector,"Supported by: amdgpu, gma500, i915, nouveau and radeon."
 ,Connector,“EDID”,BLOB | IMMUTABLE,0,Connector,Contains id of edid blob ptr object.
 ,,“DPMS”,ENUM,"{ “On”, “Standby”, “Suspend”, “Off” }",Connector,Contains DPMS operation mode value.
 ,,“PATH”,BLOB | IMMUTABLE,0,Connector,Contains topology path to a connector.
 ,,“TILE”,BLOB | IMMUTABLE,0,Connector,Contains tiling information for a connector.
 ,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Connector,CRTC that connector is attached to (atomic)
-,Plane,“type”,ENUM | IMMUTABLE,"{ ""Overlay"", ""Primary"", ""Cursor"" }",Plane,Plane type
-,,“SRC_X”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout source x coordinate in 16.16 fixed point (atomic)
-,,“SRC_Y”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout source y coordinate in 16.16 fixed point (atomic)
-,,“SRC_W”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout source width in 16.16 fixed point (atomic)
-,,“SRC_H”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout source height in 16.16 fixed point (atomic)
-,,“CRTC_X”,SIGNED_RANGE,"Min=INT_MIN, Max=INT_MAX",Plane,Scanout CRTC (destination) x coordinate (atomic)
-,,“CRTC_Y”,SIGNED_RANGE,"Min=INT_MIN, Max=INT_MAX",Plane,Scanout CRTC (destination) y coordinate (atomic)
-,,“CRTC_W”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout CRTC (destination) width (atomic)
-,,“CRTC_H”,RANGE,"Min=0, Max=UINT_MAX",Plane,Scanout CRTC (destination) height (atomic)
-,,“FB_ID”,OBJECT,DRM_MODE_OBJECT_FB,Plane,Scanout framebuffer (atomic)
-,,“CRTC_ID”,OBJECT,DRM_MODE_OBJECT_CRTC,Plane,CRTC that plane is attached to (atomic)
-,,“zpos”,RANGE,"Min=0, Max=UINT_MAX","Plane,Z-order of the plane.Planes with higher Z-order values are displayed on top, planes with identical Z-order values are display in an undefined order"
 ,DVI-I,“subconnector”,ENUM,"{ “Unknown”, “DVI-D”, “DVI-A” }",Connector,TBD
 ,,“select subconnector”,ENUM,"{ “Automatic”, “DVI-D”, “DVI-A” }",Connector,TBD
 ,TV,“subconnector”,ENUM,"{ ""Unknown"", ""Composite"", ""SVIDEO"", ""Component"", ""SCART"" }",Connector,TBD
@@ -36,12 +23,6 @@ DRM,Generic,“rotation”,BITMASK,"{ 0, ""rotate-0"" }, { 1, ""rotate-90"" }, {
 ,Virtual GPU,“suggested X”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an X offset for a connector
 ,,“suggested Y”,RANGE,"Min=0, Max=0xffffffff",Connector,property to suggest an Y offset for a connector
 ,Optional,"""aspect ratio""",ENUM,"{ ""None"", ""4:3"", ""16:9"" }",Connector,TDB
-,,“dirty”,ENUM | IMMUTABLE,"{ ""Off"", ""On"", ""Annotate"" }",Connector,TBD
-,,“DEGAMMA_LUT”,BLOB,0,CRTC,DRM property to set the degamma lookup table (LUT) mapping pixel data from the framebuffer before it is given to the transformation matrix. The data is an interpreted as an array of struct drm_color_lut elements. Hardware might choose not to use the full precision of the LUT elements nor use all the elements of the LUT (for example the hardware might choose to interpolate between LUT[0] and LUT[4]).
-,,“DEGAMMA_LUT_SIZE”,RANGE | IMMUTABLE,"Min=0, Max=UINT_MAX",CRTC,DRM property to gives the size of the lookup table to be set on the DEGAMMA_LUT property (the size depends on the underlying hardware).
-,,“CTM”,BLOB,0,CRTC,DRM property to set the current transformation matrix (CTM) apply to pixel data after the lookup through the degamma LUT and before the lookup through the gamma LUT. The data is an interpreted as a struct drm_color_ctm.
-,,“GAMMA_LUT”,BLOB,0,CRTC,DRM property to set the gamma lookup table (LUT) mapping pixel data after to the transformation matrix to data sent to the connector. The data is an interpreted as an array of struct drm_color_lut elements. Hardware might choose not to use the full precision of the LUT elements nor use all the elements of the LUT (for example the hardware might choose to interpolate between LUT[0] and LUT[4]).
-,,“GAMMA_LUT_SIZE”,RANGE | IMMUTABLE,"Min=0, Max=UINT_MAX",CRTC,DRM property to gives the size of the lookup table to be set on the GAMMA_LUT property (the size depends on the underlying hardware).
 i915,Generic,"""Broadcast RGB""",ENUM,"{ ""Automatic"", ""Full"", ""Limited 16:235"" }",Connector,"When this property is set to Limited 16:235 and CTM is set, the hardware will be programmed with the result of the multiplication of CTM by the limited range matrix to ensure the pixels normaly in the range 0..1.0 are remapped to the range 16/255..235/255."
 ,,“audio”,ENUM,"{ ""force-dvi"", ""off"", ""auto"", ""on"" }",Connector,TBD
 ,SDVO-TV,“mode”,ENUM,"{ ""NTSC_M"", ""NTSC_J"", ""NTSC_443"", ""PAL_B"" } etc.",Connector,TBD
@@ -95,7 +76,6 @@ armada,CRTC,"""CSC_YUV""",ENUM,"{ ""Auto"" , ""CCIR601"", ""CCIR709"" }",CRTC,TB
 ,,"""contrast""",RANGE,"Min=0, Max=0x7fff",Plane,TBD
 ,,"""saturation""",RANGE,"Min=0, Max=0x7fff",Plane,TBD
 exynos,CRTC,“mode”,ENUM,"{ ""normal"", ""blank"" }",CRTC,TBD
-,Overlay,“zpos”,RANGE,"Min=0, Max=MAX_PLANE-1",Plane,TBD
 i2c/ch7006_drv,Generic,“scale”,RANGE,"Min=0, Max=2",Connector,TBD
 ,TV,“mode”,ENUM,"{ ""PAL"", ""PAL-M"",""PAL-N""}, ”PAL-Nc"" , ""PAL-60"", ""NTSC-M"", ""NTSC-J"" }",Connector,TBD
 nouveau,NV10 Overlay,"""colorkey""",RANGE,"Min=0, Max=0x01ffffff",Plane,TBD
@@ -126,4 +106,3 @@ radeon,DVI-I,“coherent”,RANGE,"Min=0, Max=1",Connector,TBD
 ,FMT Dithering,“dither”,ENUM,"{ ""off"", ""on"" }",Connector,TBD
 rcar-du,Generic,"""alpha""",RANGE,"Min=0, Max=255",Plane,TBD
 ,,"""colorkey""",RANGE,"Min=0, Max=0x01ffffff",Plane,TBD
-,,"""zpos""",RANGE,"Min=1, Max=7",Plane,TBD
index abb5fdab75fdb0ec77478a48d32021232bcf56b8..b29a9e817320a844ce0a0f8a89711266a17211a0 100644 (file)
@@ -150,6 +150,7 @@ static int sync_file_set_fence(struct sync_file *sync_file,
         */
        if (num_fences == 1) {
                sync_file->fence = fences[0];
+               kfree(fences);
        } else {
                array = fence_array_create(num_fences, fences,
                                           fence_context_alloc(1), 1, false);
@@ -253,10 +254,8 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
        for (; i_b < b_num_fences; i_b++)
                add_fence(fences, &i, b_fences[i_b]);
 
-       if (i == 0) {
-               add_fence(fences, &i, a_fences[0]);
-               i++;
-       }
+       if (i == 0)
+               fences[i++] = fence_get(a_fences[0]);
 
        if (num_fences > i) {
                nfences = krealloc(fences, i * sizeof(*fences),
index 439d89b25ae096a6bf49c73d929aac25a7a4e3d2..25c720454017e69a004fccfd7efe8147cdf60b46 100644 (file)
@@ -14,7 +14,8 @@ drm-y       :=        drm_auth.o drm_bufs.o drm_cache.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_blend.o \
-               drm_encoder.o drm_mode_object.o drm_property.o
+               drm_encoder.o drm_mode_object.o drm_property.o \
+               drm_plane.o drm_color_mgmt.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
index dfb12237a6b08b8e061fb991106891948fe449b6..b63969d7887caf4d575a35a94b1c9f05ff3c126e 100644 (file)
@@ -246,7 +246,8 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 
        if (amdgpu_ttm_tt_get_usermm(bo->ttm))
                return -EPERM;
-       return drm_vma_node_verify_access(&rbo->gem_base.vma_node, filp);
+       return drm_vma_node_verify_access(&rbo->gem_base.vma_node,
+                                         filp->private_data);
 }
 
 static void amdgpu_move_null(struct ttm_buffer_object *bo,
index 6d4ff34737cb73746ce37dd7b4c00293d74c1283..28e6471257d0d799d020f7e1dac47007760fcee9 100644 (file)
@@ -198,8 +198,8 @@ static int arcpgu_probe(struct platform_device *pdev)
        int ret;
 
        drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        ret = arcpgu_load(drm);
        if (ret)
index d83b46a3032765c85fc8b00534ac550720002c8f..fb6a418ce6be611176e26bf5fa699503178e8364 100644 (file)
@@ -326,8 +326,8 @@ static int hdlcd_drm_bind(struct device *dev)
                return -ENOMEM;
 
        drm = drm_dev_alloc(&hdlcd_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        drm->dev_private = hdlcd;
        dev_set_drvdata(dev, drm);
index c383d724527f662dd3dadc15702d56442e164280..9280358b8f15219da56f1572c53e53272d27dc59 100644 (file)
@@ -311,8 +311,8 @@ static int malidp_bind(struct device *dev)
                return ret;
 
        drm = drm_dev_alloc(&malidp_driver, dev);
-       if (!drm) {
-               ret = -ENOMEM;
+       if (IS_ERR(drm)) {
+               ret = PTR_ERR(drm);
                goto alloc_fail;
        }
 
index b29a41218fc92d8c6c6cfe7157b061e69f29fb24..608df4c90520278e59bfe75d3c3348d66af51e6c 100644 (file)
@@ -150,7 +150,8 @@ static int ast_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
        struct ast_bo *astbo = ast_bo(bo);
 
-       return drm_vma_node_verify_access(&astbo->gem.vma_node, filp);
+       return drm_vma_node_verify_access(&astbo->gem.vma_node,
+                                         filp->private_data);
 }
 
 static int ast_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
index 8e7483d90c47fd5328464644673a5cededf24ac5..5f484310bee99c4ba5bbd986f47223893756db77 100644 (file)
@@ -797,8 +797,8 @@ static int atmel_hlcdc_dc_drm_probe(struct platform_device *pdev)
        int ret;
 
        ddev = drm_dev_alloc(&atmel_hlcdc_dc_driver, &pdev->dev);
-       if (!ddev)
-               return -ENOMEM;
+       if (IS_ERR(ddev))
+               return PTR_ERR(ddev);
 
        ret = atmel_hlcdc_dc_load(ddev);
        if (ret)
index 207a2cbcc1133c829dd1b2c28138bab82fbf216d..0b4e5d11704335888c0d6818a44d486675ee97ba 100644 (file)
@@ -178,7 +178,7 @@ static void bochs_encoder_init(struct drm_device *dev)
 }
 
 
-int bochs_connector_get_modes(struct drm_connector *connector)
+static int bochs_connector_get_modes(struct drm_connector *connector)
 {
        int count;
 
index 5c5638a777a12ad12c1e0fdc8d9627d7d78ea50b..269cfca9ca06834dad2fad7359c3df13f4d97c09 100644 (file)
@@ -128,7 +128,8 @@ static int bochs_bo_verify_access(struct ttm_buffer_object *bo,
 {
        struct bochs_bo *bochsbo = bochs_bo(bo);
 
-       return drm_vma_node_verify_access(&bochsbo->gem.vma_node, filp);
+       return drm_vma_node_verify_access(&bochsbo->gem.vma_node,
+                                         filp->private_data);
 }
 
 static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
index efac8aba67763e11bd5d648a93be7fdfa847d8a0..0f2e423106942456655e171f6356b0094ad0634c 100644 (file)
@@ -31,6 +31,7 @@
 #include <drm/bridge/analogix_dp.h>
 
 #include "analogix_dp_core.h"
+#include "analogix_dp_reg.h"
 
 #define to_dp(nm)      container_of(nm, struct analogix_dp_device, nm)
 
@@ -147,7 +148,7 @@ static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp)
 {
        unsigned char psr_version;
 
-       analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, &psr_version);
+       drm_dp_dpcd_readb(&dp->aux, DP_PSR_SUPPORT, &psr_version);
        dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version);
 
        return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false;
@@ -158,166 +159,37 @@ static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp)
        unsigned char psr_en;
 
        /* Disable psr function */
-       analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, &psr_en);
+       drm_dp_dpcd_readb(&dp->aux, DP_PSR_EN_CFG, &psr_en);
        psr_en &= ~DP_PSR_ENABLE;
-       analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+       drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en);
 
        /* Main-Link transmitter remains active during PSR active states */
        psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION;
-       analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+       drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en);
 
        /* Enable psr function */
        psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE |
                 DP_PSR_CRC_VERIFICATION;
-       analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en);
+       drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en);
 
        analogix_dp_enable_psr_crc(dp);
 }
 
-static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data)
-{
-       int i;
-       unsigned char sum = 0;
-
-       for (i = 0; i < EDID_BLOCK_LENGTH; i++)
-               sum = sum + edid_data[i];
-
-       return sum;
-}
-
-static int analogix_dp_read_edid(struct analogix_dp_device *dp)
-{
-       unsigned char *edid = dp->edid;
-       unsigned int extend_block = 0;
-       unsigned char sum;
-       unsigned char test_vector;
-       int retval;
-
-       /*
-        * EDID device address is 0x50.
-        * However, if necessary, you must have set upper address
-        * into E-EDID in I2C device, 0x30.
-        */
-
-       /* Read Extension Flag, Number of 128-byte EDID extension blocks */
-       retval = analogix_dp_read_byte_from_i2c(dp, I2C_EDID_DEVICE_ADDR,
-                                               EDID_EXTENSION_FLAG,
-                                               &extend_block);
-       if (retval)
-               return retval;
-
-       if (extend_block > 0) {
-               dev_dbg(dp->dev, "EDID data includes a single extension!\n");
-
-               /* Read EDID data */
-               retval = analogix_dp_read_bytes_from_i2c(dp,
-                                               I2C_EDID_DEVICE_ADDR,
-                                               EDID_HEADER_PATTERN,
-                                               EDID_BLOCK_LENGTH,
-                                               &edid[EDID_HEADER_PATTERN]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = analogix_dp_calc_edid_check_sum(edid);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               /* Read additional EDID data */
-               retval = analogix_dp_read_bytes_from_i2c(dp,
-                               I2C_EDID_DEVICE_ADDR,
-                               EDID_BLOCK_LENGTH,
-                               EDID_BLOCK_LENGTH,
-                               &edid[EDID_BLOCK_LENGTH]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = analogix_dp_calc_edid_check_sum(&edid[EDID_BLOCK_LENGTH]);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
-                                               &test_vector);
-               if (test_vector & DP_TEST_LINK_EDID_READ) {
-                       analogix_dp_write_byte_to_dpcd(dp,
-                               DP_TEST_EDID_CHECKSUM,
-                               edid[EDID_BLOCK_LENGTH + EDID_CHECKSUM]);
-                       analogix_dp_write_byte_to_dpcd(dp,
-                               DP_TEST_RESPONSE,
-                               DP_TEST_EDID_CHECKSUM_WRITE);
-               }
-       } else {
-               dev_info(dp->dev, "EDID data does not include any extensions.\n");
-
-               /* Read EDID data */
-               retval = analogix_dp_read_bytes_from_i2c(dp,
-                               I2C_EDID_DEVICE_ADDR, EDID_HEADER_PATTERN,
-                               EDID_BLOCK_LENGTH, &edid[EDID_HEADER_PATTERN]);
-               if (retval != 0) {
-                       dev_err(dp->dev, "EDID Read failed!\n");
-                       return -EIO;
-               }
-               sum = analogix_dp_calc_edid_check_sum(edid);
-               if (sum != 0) {
-                       dev_err(dp->dev, "EDID bad checksum!\n");
-                       return -EIO;
-               }
-
-               analogix_dp_read_byte_from_dpcd(dp, DP_TEST_REQUEST,
-                                               &test_vector);
-               if (test_vector & DP_TEST_LINK_EDID_READ) {
-                       analogix_dp_write_byte_to_dpcd(dp,
-                               DP_TEST_EDID_CHECKSUM, edid[EDID_CHECKSUM]);
-                       analogix_dp_write_byte_to_dpcd(dp,
-                               DP_TEST_RESPONSE, DP_TEST_EDID_CHECKSUM_WRITE);
-               }
-       }
-
-       dev_dbg(dp->dev, "EDID Read success!\n");
-       return 0;
-}
-
-static int analogix_dp_handle_edid(struct analogix_dp_device *dp)
-{
-       u8 buf[12];
-       int i;
-       int retval;
-
-       /* Read DPCD DP_DPCD_REV~RECEIVE_PORT1_CAP_1 */
-       retval = analogix_dp_read_bytes_from_dpcd(dp, DP_DPCD_REV, 12, buf);
-       if (retval)
-               return retval;
-
-       /* Read EDID */
-       for (i = 0; i < 3; i++) {
-               retval = analogix_dp_read_edid(dp);
-               if (!retval)
-                       break;
-       }
-
-       return retval;
-}
-
 static void
 analogix_dp_enable_rx_to_enhanced_mode(struct analogix_dp_device *dp,
                                       bool enable)
 {
        u8 data;
 
-       analogix_dp_read_byte_from_dpcd(dp, DP_LANE_COUNT_SET, &data);
+       drm_dp_dpcd_readb(&dp->aux, DP_LANE_COUNT_SET, &data);
 
        if (enable)
-               analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
-                                              DP_LANE_COUNT_ENHANCED_FRAME_EN |
-                                              DPCD_LANE_COUNT_SET(data));
+               drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET,
+                                  DP_LANE_COUNT_ENHANCED_FRAME_EN |
+                                       DPCD_LANE_COUNT_SET(data));
        else
-               analogix_dp_write_byte_to_dpcd(dp, DP_LANE_COUNT_SET,
-                                              DPCD_LANE_COUNT_SET(data));
+               drm_dp_dpcd_writeb(&dp->aux, DP_LANE_COUNT_SET,
+                                  DPCD_LANE_COUNT_SET(data));
 }
 
 static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp)
@@ -325,7 +197,7 @@ static int analogix_dp_is_enhanced_mode_available(struct analogix_dp_device *dp)
        u8 data;
        int retval;
 
-       analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
+       drm_dp_dpcd_readb(&dp->aux, DP_MAX_LANE_COUNT, &data);
        retval = DPCD_ENHANCED_FRAME_CAP(data);
 
        return retval;
@@ -344,8 +216,8 @@ static void analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
 {
        analogix_dp_set_training_pattern(dp, DP_NONE);
 
-       analogix_dp_write_byte_to_dpcd(dp, DP_TRAINING_PATTERN_SET,
-                                      DP_TRAINING_PATTERN_DISABLE);
+       drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+                          DP_TRAINING_PATTERN_DISABLE);
 }
 
 static void
@@ -390,8 +262,8 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
        /* Setup RX configuration */
        buf[0] = dp->link_train.link_rate;
        buf[1] = dp->link_train.lane_count;
-       retval = analogix_dp_write_bytes_to_dpcd(dp, DP_LINK_BW_SET, 2, buf);
-       if (retval)
+       retval = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, 2);
+       if (retval < 0)
                return retval;
 
        /* Set TX pre-emphasis to minimum */
@@ -415,20 +287,22 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
        analogix_dp_set_training_pattern(dp, TRAINING_PTN1);
 
        /* Set RX training pattern */
-       retval = analogix_dp_write_byte_to_dpcd(dp,
-                       DP_TRAINING_PATTERN_SET,
-                       DP_LINK_SCRAMBLING_DISABLE | DP_TRAINING_PATTERN_1);
-       if (retval)
+       retval = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+                                   DP_LINK_SCRAMBLING_DISABLE |
+                                       DP_TRAINING_PATTERN_1);
+       if (retval < 0)
                return retval;
 
        for (lane = 0; lane < lane_count; lane++)
                buf[lane] = DP_TRAIN_PRE_EMPH_LEVEL_0 |
                            DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
 
-       retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
-                                                lane_count, buf);
+       retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf,
+                                  lane_count);
+       if (retval < 0)
+               return retval;
 
-       return retval;
+       return 0;
 }
 
 static unsigned char analogix_dp_get_lane_status(u8 link_status[2], int lane)
@@ -580,25 +454,23 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
 
        lane_count = dp->link_train.lane_count;
 
-       retval =  analogix_dp_read_bytes_from_dpcd(dp,
-                       DP_LANE0_1_STATUS, 2, link_status);
-       if (retval)
+       retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2);
+       if (retval < 0)
                return retval;
 
-       retval =  analogix_dp_read_bytes_from_dpcd(dp,
-                       DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-       if (retval)
+       retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
+                                 adjust_request, 2);
+       if (retval < 0)
                return retval;
 
        if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
                /* set training pattern 2 for EQ */
                analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
 
-               retval = analogix_dp_write_byte_to_dpcd(dp,
-                               DP_TRAINING_PATTERN_SET,
-                               DP_LINK_SCRAMBLING_DISABLE |
-                               DP_TRAINING_PATTERN_2);
-               if (retval)
+               retval = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+                                           DP_LINK_SCRAMBLING_DISABLE |
+                                               DP_TRAINING_PATTERN_2);
+               if (retval < 0)
                        return retval;
 
                dev_info(dp->dev, "Link Training Clock Recovery success\n");
@@ -636,13 +508,12 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
                analogix_dp_set_lane_link_training(dp,
                        dp->link_train.training_lane[lane], lane);
 
-       retval = analogix_dp_write_bytes_to_dpcd(dp,
-                       DP_TRAINING_LANE0_SET, lane_count,
-                       dp->link_train.training_lane);
-       if (retval)
+       retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+                                  dp->link_train.training_lane, lane_count);
+       if (retval < 0)
                return retval;
 
-       return retval;
+       return 0;
 }
 
 static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
@@ -655,9 +526,8 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
 
        lane_count = dp->link_train.lane_count;
 
-       retval = analogix_dp_read_bytes_from_dpcd(dp,
-                       DP_LANE0_1_STATUS, 2, link_status);
-       if (retval)
+       retval = drm_dp_dpcd_read(&dp->aux, DP_LANE0_1_STATUS, link_status, 2);
+       if (retval < 0)
                return retval;
 
        if (analogix_dp_clock_recovery_ok(link_status, lane_count)) {
@@ -665,14 +535,14 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
                return -EIO;
        }
 
-       retval = analogix_dp_read_bytes_from_dpcd(dp,
-                       DP_ADJUST_REQUEST_LANE0_1, 2, adjust_request);
-       if (retval)
+       retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
+                                 adjust_request, 2);
+       if (retval < 0)
                return retval;
 
-       retval = analogix_dp_read_byte_from_dpcd(dp,
-                       DP_LANE_ALIGN_STATUS_UPDATED, &link_align);
-       if (retval)
+       retval = drm_dp_dpcd_readb(&dp->aux, DP_LANE_ALIGN_STATUS_UPDATED,
+                                  &link_align);
+       if (retval < 0)
                return retval;
 
        analogix_dp_get_adjust_training_lane(dp, adjust_request);
@@ -713,10 +583,12 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
                analogix_dp_set_lane_link_training(dp,
                        dp->link_train.training_lane[lane], lane);
 
-       retval = analogix_dp_write_bytes_to_dpcd(dp, DP_TRAINING_LANE0_SET,
-                       lane_count, dp->link_train.training_lane);
+       retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
+                                  dp->link_train.training_lane, lane_count);
+       if (retval < 0)
+               return retval;
 
-       return retval;
+       return 0;
 }
 
 static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp,
@@ -730,7 +602,7 @@ static void analogix_dp_get_max_rx_bandwidth(struct analogix_dp_device *dp,
         * For DP rev.1.2, Maximum link rate of Main Link lanes
         * 0x06 = 1.62 Gbps, 0x0a = 2.7 Gbps, 0x14 = 5.4Gbps
         */
-       analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LINK_RATE, &data);
+       drm_dp_dpcd_readb(&dp->aux, DP_MAX_LINK_RATE, &data);
        *bandwidth = data;
 }
 
@@ -743,7 +615,7 @@ static void analogix_dp_get_max_rx_lane_count(struct analogix_dp_device *dp,
         * For DP rev.1.1, Maximum number of Main Link lanes
         * 0x01 = 1 lane, 0x02 = 2 lanes, 0x04 = 4 lanes
         */
-       analogix_dp_read_byte_from_dpcd(dp, DP_MAX_LANE_COUNT, &data);
+       drm_dp_dpcd_readb(&dp->aux, DP_MAX_LANE_COUNT, &data);
        *lane_count = DPCD_MAX_LANE_COUNT(data);
 }
 
@@ -912,19 +784,15 @@ static void analogix_dp_enable_scramble(struct analogix_dp_device *dp,
        if (enable) {
                analogix_dp_enable_scrambling(dp);
 
-               analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
-                                               &data);
-               analogix_dp_write_byte_to_dpcd(dp,
-                       DP_TRAINING_PATTERN_SET,
-                       (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE));
+               drm_dp_dpcd_readb(&dp->aux, DP_TRAINING_PATTERN_SET, &data);
+               drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+                                  (u8)(data & ~DP_LINK_SCRAMBLING_DISABLE));
        } else {
                analogix_dp_disable_scrambling(dp);
 
-               analogix_dp_read_byte_from_dpcd(dp, DP_TRAINING_PATTERN_SET,
-                                               &data);
-               analogix_dp_write_byte_to_dpcd(dp,
-                       DP_TRAINING_PATTERN_SET,
-                       (u8)(data | DP_LINK_SCRAMBLING_DISABLE));
+               drm_dp_dpcd_readb(&dp->aux, DP_TRAINING_PATTERN_SET, &data);
+               drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET,
+                                  (u8)(data | DP_LINK_SCRAMBLING_DISABLE));
        }
 }
 
@@ -1050,33 +918,37 @@ out:
        return ret;
 }
 
-int analogix_dp_get_modes(struct drm_connector *connector)
+static int analogix_dp_get_modes(struct drm_connector *connector)
 {
        struct analogix_dp_device *dp = to_dp(connector);
-       struct edid *edid = (struct edid *)dp->edid;
+       struct edid *edid;
        int ret, num_modes = 0;
 
-       ret = analogix_dp_prepare_panel(dp, true, false);
-       if (ret) {
-               DRM_ERROR("Failed to prepare panel (%d)\n", ret);
-               return 0;
-       }
+       if (dp->plat_data->panel) {
+               num_modes += drm_panel_get_modes(dp->plat_data->panel);
+       } else {
+               ret = analogix_dp_prepare_panel(dp, true, false);
+               if (ret) {
+                       DRM_ERROR("Failed to prepare panel (%d)\n", ret);
+                       return 0;
+               }
 
-       if (analogix_dp_handle_edid(dp) == 0) {
-               drm_mode_connector_update_edid_property(&dp->connector, edid);
-               num_modes += drm_add_edid_modes(&dp->connector, edid);
-       }
+               edid = drm_get_edid(connector, &dp->aux.ddc);
+               if (edid) {
+                       drm_mode_connector_update_edid_property(&dp->connector,
+                                                               edid);
+                       num_modes += drm_add_edid_modes(&dp->connector, edid);
+                       kfree(edid);
+               }
 
-       if (dp->plat_data->panel)
-               num_modes += drm_panel_get_modes(dp->plat_data->panel);
+               ret = analogix_dp_prepare_panel(dp, false, false);
+               if (ret)
+                       DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
+       }
 
        if (dp->plat_data->get_modes)
                num_modes += dp->plat_data->get_modes(dp->plat_data, connector);
 
-       ret = analogix_dp_prepare_panel(dp, false, false);
-       if (ret)
-               DRM_ERROR("Failed to unprepare panel (%d)\n", ret);
-
        return num_modes;
 }
 
@@ -1093,13 +965,16 @@ static const struct drm_connector_helper_funcs analogix_dp_connector_helper_func
        .best_encoder = analogix_dp_best_encoder,
 };
 
-enum drm_connector_status
+static enum drm_connector_status
 analogix_dp_detect(struct drm_connector *connector, bool force)
 {
        struct analogix_dp_device *dp = to_dp(connector);
        enum drm_connector_status status = connector_status_disconnected;
        int ret;
 
+       if (dp->plat_data->panel)
+               return connector_status_connected;
+
        ret = analogix_dp_prepare_panel(dp, true, false);
        if (ret) {
                DRM_ERROR("Failed to prepare panel (%d)\n", ret);
@@ -1395,6 +1270,14 @@ static int analogix_dp_dt_parse_pdata(struct analogix_dp_device *dp)
        return 0;
 }
 
+static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux,
+                                      struct drm_dp_aux_msg *msg)
+{
+       struct analogix_dp_device *dp = to_dp(aux);
+
+       return analogix_dp_transfer(dp, msg);
+}
+
 int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
                     struct analogix_dp_plat_data *plat_data)
 {
@@ -1515,6 +1398,14 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev,
        dp->drm_dev = drm_dev;
        dp->encoder = dp->plat_data->encoder;
 
+       dp->aux.name = "DP-AUX";
+       dp->aux.transfer = analogix_dpaux_transfer;
+       dp->aux.dev = &pdev->dev;
+
+       ret = drm_dp_aux_register(&dp->aux);
+       if (ret)
+               goto err_disable_pm_runtime;
+
        ret = analogix_dp_create_bridge(drm_dev, dp);
        if (ret) {
                DRM_ERROR("failed to create bridge (%d)\n", ret);
index 473b9802b2d68d5acf66454de2b7c609a67f224d..5c6a28806129a4e6d2eb668db7e306f9d772877c 100644 (file)
 #define MAX_CR_LOOP 5
 #define MAX_EQ_LOOP 5
 
-/* I2C EDID Chip ID, Slave Address */
-#define I2C_EDID_DEVICE_ADDR                   0x50
-#define I2C_E_EDID_DEVICE_ADDR                 0x30
-
-#define EDID_BLOCK_LENGTH                      0x80
-#define EDID_HEADER_PATTERN                    0x00
-#define EDID_EXTENSION_FLAG                    0x7e
-#define EDID_CHECKSUM                          0x7f
-
 /* DP_MAX_LANE_COUNT */
 #define DPCD_ENHANCED_FRAME_CAP(x)             (((x) >> 7) & 0x1)
 #define DPCD_MAX_LANE_COUNT(x)                 ((x) & 0x1f)
@@ -166,6 +157,7 @@ struct analogix_dp_device {
        struct drm_device       *drm_dev;
        struct drm_connector    connector;
        struct drm_bridge       *bridge;
+       struct drm_dp_aux       aux;
        struct clk              *clock;
        unsigned int            irq;
        void __iomem            *reg_base;
@@ -176,7 +168,6 @@ struct analogix_dp_device {
        int                     dpms_mode;
        int                     hpd_gpio;
        bool                    force_hpd;
-       unsigned char           edid[EDID_BLOCK_LENGTH * 2];
        bool                    psr_support;
 
        struct mutex            panel_lock;
@@ -210,33 +201,6 @@ void analogix_dp_reset_aux(struct analogix_dp_device *dp);
 void analogix_dp_init_aux(struct analogix_dp_device *dp);
 int analogix_dp_get_plug_in_status(struct analogix_dp_device *dp);
 void analogix_dp_enable_sw_function(struct analogix_dp_device *dp);
-int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp);
-int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
-                                  unsigned int reg_addr,
-                                  unsigned char data);
-int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
-                                   unsigned int reg_addr,
-                                   unsigned char *data);
-int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
-                                   unsigned int reg_addr,
-                                   unsigned int count,
-                                   unsigned char data[]);
-int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
-                                    unsigned int reg_addr,
-                                    unsigned int count,
-                                    unsigned char data[]);
-int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
-                                 unsigned int device_addr,
-                                 unsigned int reg_addr);
-int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
-                                  unsigned int device_addr,
-                                  unsigned int reg_addr,
-                                  unsigned int *data);
-int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
-                                   unsigned int device_addr,
-                                   unsigned int reg_addr,
-                                   unsigned int count,
-                                   unsigned char edid[]);
 void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype);
 void analogix_dp_get_link_bandwidth(struct analogix_dp_device *dp, u32 *bwtype);
 void analogix_dp_set_lane_count(struct analogix_dp_device *dp, u32 count);
@@ -285,5 +249,7 @@ void analogix_dp_disable_scrambling(struct analogix_dp_device *dp);
 void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp);
 void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
                              struct edp_vsc_psr *vsc);
+ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
+                            struct drm_dp_aux_msg *msg);
 
 #endif /* _ANALOGIX_DP_CORE_H */
index fae0293d509ad471a4a7ace7d4f44283230c9514..cd37ac058675f7c00038dd774ac083fdb8196fd8 100644 (file)
@@ -585,330 +585,6 @@ int analogix_dp_write_byte_to_dpcd(struct analogix_dp_device *dp,
        return retval;
 }
 
-int analogix_dp_read_byte_from_dpcd(struct analogix_dp_device *dp,
-                                   unsigned int reg_addr,
-                                   unsigned char *data)
-{
-       u32 reg;
-       int i;
-       int retval;
-
-       for (i = 0; i < 3; i++) {
-               /* Clear AUX CH data buffer */
-               reg = BUF_CLR;
-               writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
-
-               /* Select DPCD device address */
-               reg = AUX_ADDR_7_0(reg_addr);
-               writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
-               reg = AUX_ADDR_15_8(reg_addr);
-               writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
-               reg = AUX_ADDR_19_16(reg_addr);
-               writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
-
-               /*
-                * Set DisplayPort transaction and read 1 byte
-                * If bit 3 is 1, DisplayPort transaction.
-                * If Bit 3 is 0, I2C transaction.
-                */
-               reg = AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-               writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
-
-               /* Start AUX transaction */
-               retval = analogix_dp_start_aux_transaction(dp);
-               if (retval == 0)
-                       break;
-
-               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-       }
-
-       /* Read data buffer */
-       reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
-       *data = (unsigned char)(reg & 0xff);
-
-       return retval;
-}
-
-int analogix_dp_write_bytes_to_dpcd(struct analogix_dp_device *dp,
-                                   unsigned int reg_addr,
-                                   unsigned int count,
-                                   unsigned char data[])
-{
-       u32 reg;
-       unsigned int start_offset;
-       unsigned int cur_data_count;
-       unsigned int cur_data_idx;
-       int i;
-       int retval = 0;
-
-       /* Clear AUX CH data buffer */
-       reg = BUF_CLR;
-       writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
-
-       start_offset = 0;
-       while (start_offset < count) {
-               /* Buffer size of AUX CH is 16 * 4bytes */
-               if ((count - start_offset) > 16)
-                       cur_data_count = 16;
-               else
-                       cur_data_count = count - start_offset;
-
-               for (i = 0; i < 3; i++) {
-                       /* Select DPCD device address */
-                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
-                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
-                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
-
-                       for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-                            cur_data_idx++) {
-                               reg = data[start_offset + cur_data_idx];
-                               writel(reg, dp->reg_base +
-                                      ANALOGIX_DP_BUF_DATA_0 +
-                                      4 * cur_data_idx);
-                       }
-
-                       /*
-                        * Set DisplayPort transaction and write
-                        * If bit 3 is 1, DisplayPort transaction.
-                        * If Bit 3 is 0, I2C transaction.
-                        */
-                       reg = AUX_LENGTH(cur_data_count) |
-                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_WRITE;
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
-
-                       /* Start AUX transaction */
-                       retval = analogix_dp_start_aux_transaction(dp);
-                       if (retval == 0)
-                               break;
-
-                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                               __func__);
-               }
-
-               start_offset += cur_data_count;
-       }
-
-       return retval;
-}
-
-int analogix_dp_read_bytes_from_dpcd(struct analogix_dp_device *dp,
-                                    unsigned int reg_addr,
-                                    unsigned int count,
-                                    unsigned char data[])
-{
-       u32 reg;
-       unsigned int start_offset;
-       unsigned int cur_data_count;
-       unsigned int cur_data_idx;
-       int i;
-       int retval = 0;
-
-       /* Clear AUX CH data buffer */
-       reg = BUF_CLR;
-       writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
-
-       start_offset = 0;
-       while (start_offset < count) {
-               /* Buffer size of AUX CH is 16 * 4bytes */
-               if ((count - start_offset) > 16)
-                       cur_data_count = 16;
-               else
-                       cur_data_count = count - start_offset;
-
-               /* AUX CH Request Transaction process */
-               for (i = 0; i < 3; i++) {
-                       /* Select DPCD device address */
-                       reg = AUX_ADDR_7_0(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
-                       reg = AUX_ADDR_15_8(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
-                       reg = AUX_ADDR_19_16(reg_addr + start_offset);
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
-
-                       /*
-                        * Set DisplayPort transaction and read
-                        * If bit 3 is 1, DisplayPort transaction.
-                        * If Bit 3 is 0, I2C transaction.
-                        */
-                       reg = AUX_LENGTH(cur_data_count) |
-                               AUX_TX_COMM_DP_TRANSACTION | AUX_TX_COMM_READ;
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
-
-                       /* Start AUX transaction */
-                       retval = analogix_dp_start_aux_transaction(dp);
-                       if (retval == 0)
-                               break;
-
-                       dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                               __func__);
-               }
-
-               for (cur_data_idx = 0; cur_data_idx < cur_data_count;
-                   cur_data_idx++) {
-                       reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0
-                                                + 4 * cur_data_idx);
-                       data[start_offset + cur_data_idx] =
-                               (unsigned char)reg;
-               }
-
-               start_offset += cur_data_count;
-       }
-
-       return retval;
-}
-
-int analogix_dp_select_i2c_device(struct analogix_dp_device *dp,
-                                 unsigned int device_addr,
-                                 unsigned int reg_addr)
-{
-       u32 reg;
-       int retval;
-
-       /* Set EDID device address */
-       reg = device_addr;
-       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
-       writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
-       writel(0x0, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
-
-       /* Set offset from base address of EDID device */
-       writel(reg_addr, dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
-
-       /*
-        * Set I2C transaction and write address
-        * If bit 3 is 1, DisplayPort transaction.
-        * If Bit 3 is 0, I2C transaction.
-        */
-       reg = AUX_TX_COMM_I2C_TRANSACTION | AUX_TX_COMM_MOT |
-               AUX_TX_COMM_WRITE;
-       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
-
-       /* Start AUX transaction */
-       retval = analogix_dp_start_aux_transaction(dp);
-       if (retval != 0)
-               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-
-       return retval;
-}
-
-int analogix_dp_read_byte_from_i2c(struct analogix_dp_device *dp,
-                                  unsigned int device_addr,
-                                  unsigned int reg_addr,
-                                  unsigned int *data)
-{
-       u32 reg;
-       int i;
-       int retval;
-
-       for (i = 0; i < 3; i++) {
-               /* Clear AUX CH data buffer */
-               reg = BUF_CLR;
-               writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
-
-               /* Select EDID device */
-               retval = analogix_dp_select_i2c_device(dp, device_addr,
-                                                      reg_addr);
-               if (retval != 0)
-                       continue;
-
-               /*
-                * Set I2C transaction and read data
-                * If bit 3 is 1, DisplayPort transaction.
-                * If Bit 3 is 0, I2C transaction.
-                */
-               reg = AUX_TX_COMM_I2C_TRANSACTION |
-                       AUX_TX_COMM_READ;
-               writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
-
-               /* Start AUX transaction */
-               retval = analogix_dp_start_aux_transaction(dp);
-               if (retval == 0)
-                       break;
-
-               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n", __func__);
-       }
-
-       /* Read data */
-       if (retval == 0)
-               *data = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0);
-
-       return retval;
-}
-
-int analogix_dp_read_bytes_from_i2c(struct analogix_dp_device *dp,
-                                   unsigned int device_addr,
-                                   unsigned int reg_addr,
-                                   unsigned int count,
-                                   unsigned char edid[])
-{
-       u32 reg;
-       unsigned int i, j;
-       unsigned int cur_data_idx;
-       unsigned int defer = 0;
-       int retval = 0;
-
-       for (i = 0; i < count; i += 16) {
-               for (j = 0; j < 3; j++) {
-                       /* Clear AUX CH data buffer */
-                       reg = BUF_CLR;
-                       writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
-
-                       /* Set normal AUX CH command */
-                       reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
-                       reg &= ~ADDR_ONLY;
-                       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
-
-                       /*
-                        * If Rx sends defer, Tx sends only reads
-                        * request without sending address
-                        */
-                       if (!defer)
-                               retval = analogix_dp_select_i2c_device(dp,
-                                               device_addr, reg_addr + i);
-                       else
-                               defer = 0;
-
-                       if (retval == 0) {
-                               /*
-                                * Set I2C transaction and write data
-                                * If bit 3 is 1, DisplayPort transaction.
-                                * If Bit 3 is 0, I2C transaction.
-                                */
-                               reg = AUX_LENGTH(16) |
-                                       AUX_TX_COMM_I2C_TRANSACTION |
-                                       AUX_TX_COMM_READ;
-                               writel(reg, dp->reg_base +
-                                       ANALOGIX_DP_AUX_CH_CTL_1);
-
-                               /* Start AUX transaction */
-                               retval = analogix_dp_start_aux_transaction(dp);
-                               if (retval == 0)
-                                       break;
-
-                               dev_dbg(dp->dev, "%s: Aux Transaction fail!\n",
-                                       __func__);
-                       }
-                       /* Check if Rx sends defer */
-                       reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM);
-                       if (reg == AUX_RX_COMM_AUX_DEFER ||
-                           reg == AUX_RX_COMM_I2C_DEFER) {
-                               dev_err(dp->dev, "Defer: %d\n\n", reg);
-                               defer = 1;
-                       }
-               }
-
-               for (cur_data_idx = 0; cur_data_idx < 16; cur_data_idx++) {
-                       reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0
-                                                + 4 * cur_data_idx);
-                       edid[i + cur_data_idx] = (unsigned char)reg;
-               }
-       }
-
-       return retval;
-}
-
 void analogix_dp_set_link_bandwidth(struct analogix_dp_device *dp, u32 bwtype)
 {
        u32 reg;
@@ -1361,3 +1037,130 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device *dp,
        val |= IF_EN;
        writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL);
 }
+
+ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
+                            struct drm_dp_aux_msg *msg)
+{
+       u32 reg;
+       u8 *buffer = msg->buffer;
+       int timeout_loop = 0;
+       unsigned int i;
+       int num_transferred = 0;
+
+       /* Buffer size of AUX CH is 16 bytes */
+       if (WARN_ON(msg->size > 16))
+               return -E2BIG;
+
+       /* Clear AUX CH data buffer */
+       reg = BUF_CLR;
+       writel(reg, dp->reg_base + ANALOGIX_DP_BUFFER_DATA_CTL);
+
+       switch (msg->request & ~DP_AUX_I2C_MOT) {
+       case DP_AUX_I2C_WRITE:
+               reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_I2C_TRANSACTION;
+               if (msg->request & DP_AUX_I2C_MOT)
+                       reg |= AUX_TX_COMM_MOT;
+               break;
+
+       case DP_AUX_I2C_READ:
+               reg = AUX_TX_COMM_READ | AUX_TX_COMM_I2C_TRANSACTION;
+               if (msg->request & DP_AUX_I2C_MOT)
+                       reg |= AUX_TX_COMM_MOT;
+               break;
+
+       case DP_AUX_NATIVE_WRITE:
+               reg = AUX_TX_COMM_WRITE | AUX_TX_COMM_DP_TRANSACTION;
+               break;
+
+       case DP_AUX_NATIVE_READ:
+               reg = AUX_TX_COMM_READ | AUX_TX_COMM_DP_TRANSACTION;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       reg |= AUX_LENGTH(msg->size);
+       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_1);
+
+       /* Select DPCD device address */
+       reg = AUX_ADDR_7_0(msg->address);
+       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_7_0);
+       reg = AUX_ADDR_15_8(msg->address);
+       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_15_8);
+       reg = AUX_ADDR_19_16(msg->address);
+       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_ADDR_19_16);
+
+       if (!(msg->request & DP_AUX_I2C_READ)) {
+               for (i = 0; i < msg->size; i++) {
+                       reg = buffer[i];
+                       writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
+                              4 * i);
+                       num_transferred++;
+               }
+       }
+
+       /* Enable AUX CH operation */
+       reg = AUX_EN;
+
+       /* Zero-sized messages specify address-only transactions. */
+       if (msg->size < 1)
+               reg |= ADDR_ONLY;
+
+       writel(reg, dp->reg_base + ANALOGIX_DP_AUX_CH_CTL_2);
+
+       /* Is AUX CH command reply received? */
+       /* TODO: Wait for an interrupt instead of looping? */
+       reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+       while (!(reg & RPLY_RECEIV)) {
+               timeout_loop++;
+               if (timeout_loop > DP_TIMEOUT_LOOP_COUNT) {
+                       dev_err(dp->dev, "AUX CH command reply failed!\n");
+                       return -ETIMEDOUT;
+               }
+               reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+               usleep_range(10, 11);
+       }
+
+       /* Clear interrupt source for AUX CH command reply */
+       writel(RPLY_RECEIV, dp->reg_base + ANALOGIX_DP_INT_STA);
+
+       /* Clear interrupt source for AUX CH access error */
+       reg = readl(dp->reg_base + ANALOGIX_DP_INT_STA);
+       if (reg & AUX_ERR) {
+               writel(AUX_ERR, dp->reg_base + ANALOGIX_DP_INT_STA);
+               return -EREMOTEIO;
+       }
+
+       /* Check AUX CH error access status */
+       reg = readl(dp->reg_base + ANALOGIX_DP_AUX_CH_STA);
+       if ((reg & AUX_STATUS_MASK)) {
+               dev_err(dp->dev, "AUX CH error happened: %d\n\n",
+                       reg & AUX_STATUS_MASK);
+               return -EREMOTEIO;
+       }
+
+       if (msg->request & DP_AUX_I2C_READ) {
+               for (i = 0; i < msg->size; i++) {
+                       reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
+                                   4 * i);
+                       buffer[i] = (unsigned char)reg;
+                       num_transferred++;
+               }
+       }
+
+       /* Check if Rx sends defer */
+       reg = readl(dp->reg_base + ANALOGIX_DP_AUX_RX_COMM);
+       if (reg == AUX_RX_COMM_AUX_DEFER)
+               msg->reply = DP_AUX_NATIVE_REPLY_DEFER;
+       else if (reg == AUX_RX_COMM_I2C_DEFER)
+               msg->reply = DP_AUX_I2C_REPLY_DEFER;
+       else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_WRITE ||
+                (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_I2C_READ)
+               msg->reply = DP_AUX_I2C_REPLY_ACK;
+       else if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE ||
+                (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
+               msg->reply = DP_AUX_NATIVE_REPLY_ACK;
+
+       return num_transferred;
+}
index 1cc9ee607128772295bf6f49c8ba9ad93f73abd1..bb2438dd8733f4c2c64618629abf1e946395f02a 100644 (file)
@@ -150,7 +150,8 @@ static int cirrus_bo_verify_access(struct ttm_buffer_object *bo, struct file *fi
 {
        struct cirrus_bo *cirrusbo = cirrus_bo(bo);
 
-       return drm_vma_node_verify_access(&cirrusbo->gem.vma_node, filp);
+       return drm_vma_node_verify_access(&cirrusbo->gem.vma_node,
+                                         filp->private_data);
 }
 
 static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
index ea78d70de9f38eba1eb2e1d0de24e3d6035ea6e4..c3f83476f99601c2ff91711b602c902b55170f71 100644 (file)
@@ -1693,7 +1693,7 @@ fail:
 }
 EXPORT_SYMBOL(drm_atomic_helper_prepare_planes);
 
-bool plane_crtc_active(struct drm_plane_state *state)
+static bool plane_crtc_active(const struct drm_plane_state *state)
 {
        return state->crtc && state->crtc->state->active;
 }
index 0813b7e021be815316ee89b93cfe214984e5a81b..85172a977bf3eccf5ec3ea3b1a83797364a396e4 100644 (file)
  */
 #include <drm/drmP.h>
 #include <drm/drm_atomic.h>
-#include <drm/drm_crtc.h>
+#include <drm/drm_blend.h>
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
 
-#include "drm_internal.h"
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * The basic plane composition model supported by standard plane properties only
+ * has a source rectangle (in logical pixels within the &drm_framebuffer), with
+ * sub-pixel accuracy, which is scaled up to a pixel-aligned destination
+ * rectangle in the visible area of a &drm_crtc. The visible area of a CRTC is
+ * defined by the horizontal and vertical visible pixels (stored in @hdisplay
+ * and @vdisplay) of the requested mode (stored in @mode in the
+ * &drm_crtc_state). These two rectangles are both stored in the
+ * &drm_plane_state.
+ *
+ * For the atomic ioctl the following standard (atomic) properties on the plane object
+ * encode the basic plane composition model:
+ *
+ * SRC_X:
+ *     X coordinate offset for the source rectangle within the
+ *     &drm_framebuffer, in 16.16 fixed point. Must be positive.
+ * SRC_Y:
+ *     Y coordinate offset for the source rectangle within the
+ *     &drm_framebuffer, in 16.16 fixed point. Must be positive.
+ * SRC_W:
+ *     Width for the source rectangle within the &drm_framebuffer, in 16.16
+ *     fixed point. SRC_X plus SRC_W must be within the width of the source
+ *     framebuffer. Must be positive.
+ * SRC_H:
+ *     Height for the source rectangle within the &drm_framebuffer, in 16.16
+ *     fixed point. SRC_Y plus SRC_H must be within the height of the source
+ *     framebuffer. Must be positive.
+ * CRTC_X:
+ *     X coordinate offset for the destination rectangle. Can be negative.
+ * CRTC_Y:
+ *     Y coordinate offset for the destination rectangle. Can be negative.
+ * CRTC_W:
+ *     Width for the destination rectangle. CRTC_X plus CRTC_W can extend past
+ *     the currently visible horizontal area of the &drm_crtc.
+ * CRTC_H:
+ *     Height for the destination rectangle. CRTC_Y plus CRTC_H can extend past
+ *     the currently visible vertical area of the &drm_crtc.
+ * FB_ID:
+ *     Mode object ID of the &drm_framebuffer this plane should scan out.
+ * CRTC_ID:
+ *     Mode object ID of the &drm_crtc this plane should be connected to.
+ *
+ * Note that the source rectangle must fully lie within the bounds of the
+ * &drm_framebuffer. The destination rectangle can lie outside of the visible
+ * area of the current mode of the CRTC. It must be apprpriately clipped by the
+ * driver, which can be done by calling drm_plane_helper_check_update(). Drivers
+ * are also allowed to round the subpixel sampling positions appropriately, but
+ * only to the next full pixel. No pixel outside of the source rectangle may
+ * ever be sampled, which is important when applying more sophisticated
+ * filtering than just a bilinear one when scaling. The filtering mode when
+ * scaling is unspecified.
+ *
+ * On top of this basic transformation additional properties can be exposed by
+ * the driver:
+ *
+ * - Rotation is set up with drm_mode_create_rotation_property(). It adds a
+ *   rotation and reflection step between the source and destination rectangles.
+ *   Without this property the rectangle is only scaled, but not rotated or
+ *   reflected.
+ *
+ * - Z position is set up with drm_plane_create_zpos_immutable_property() and
+ *   drm_plane_create_zpos_property(). It controls the visibility of overlapping
+ *   planes. Without this property the primary plane is always below the cursor
+ *   plane, and ordering between all other planes is undefined.
+ *
+ * Note that all the property extensions described here apply either to the
+ * plane or the CRTC (e.g. for the background color, which currently is not
+ * exposed and assumed to be black).
+ */
+
+/**
+ * drm_mode_create_rotation_property - create a new rotation property
+ * @dev: DRM device
+ * @supported_rotations: bitmask of supported rotations and reflections
+ *
+ * This creates a new property with the selected support for transformations.
+ * The resulting property should be stored in @rotation_property in
+ * &drm_mode_config. It then must be attached to each plane which supports
+ * rotations using drm_object_attach_property().
+ *
+ * FIXME: Probably better if the rotation property is created on each plane,
+ * like the zpos property. Otherwise it's not possible to allow different
+ * rotation modes on different planes.
+ *
+ * Since a rotation by 180° degress is the same as reflecting both along the x
+ * and the y axis the rotation property is somewhat redundant. Drivers can use
+ * drm_rotation_simplify() to normalize values of this property.
+ *
+ * The property exposed to userspace is a bitmask property (see
+ * drm_property_create_bitmask()) called "rotation" and has the following
+ * bitmask enumaration values:
+ *
+ * DRM_ROTATE_0:
+ *     "rotate-0"
+ * DRM_ROTATE_90:
+ *     "rotate-90"
+ * DRM_ROTATE_180:
+ *     "rotate-180"
+ * DRM_ROTATE_270:
+ *     "rotate-270"
+ * DRM_REFLECT_X:
+ *     "reflect-x"
+ * DRM_REFELCT_Y:
+ *     "reflect-y"
+ *
+ * Rotation is the specified amount in degrees in counter clockwise direction,
+ * the X and Y axis are within the source rectangle, i.e.  the X/Y axis before
+ * rotation. After reflection, the rotation is applied to the image sampled from
+ * the source rectangle, before scaling it to fit the destination rectangle.
+ */
+struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
+                                                      unsigned int supported_rotations)
+{
+       static const struct drm_prop_enum_list props[] = {
+               { __builtin_ffs(DRM_ROTATE_0) - 1,   "rotate-0" },
+               { __builtin_ffs(DRM_ROTATE_90) - 1,  "rotate-90" },
+               { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" },
+               { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" },
+               { __builtin_ffs(DRM_REFLECT_X) - 1,  "reflect-x" },
+               { __builtin_ffs(DRM_REFLECT_Y) - 1,  "reflect-y" },
+       };
+
+       return drm_property_create_bitmask(dev, 0, "rotation",
+                                          props, ARRAY_SIZE(props),
+                                          supported_rotations);
+}
+EXPORT_SYMBOL(drm_mode_create_rotation_property);
+
+/**
+ * drm_rotation_simplify() - Try to simplify the rotation
+ * @rotation: Rotation to be simplified
+ * @supported_rotations: Supported rotations
+ *
+ * Attempt to simplify the rotation to a form that is supported.
+ * Eg. if the hardware supports everything except DRM_REFLECT_X
+ * one could call this function like this:
+ *
+ * drm_rotation_simplify(rotation, DRM_ROTATE_0 |
+ *                       DRM_ROTATE_90 | DRM_ROTATE_180 |
+ *                       DRM_ROTATE_270 | DRM_REFLECT_Y);
+ *
+ * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
+ * transforms the hardware supports, this function may not
+ * be able to produce a supported transform, so the caller should
+ * check the result afterwards.
+ */
+unsigned int drm_rotation_simplify(unsigned int rotation,
+                                  unsigned int supported_rotations)
+{
+       if (rotation & ~supported_rotations) {
+               rotation ^= DRM_REFLECT_X | DRM_REFLECT_Y;
+               rotation = (rotation & DRM_REFLECT_MASK) |
+                          BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
+       }
+
+       return rotation;
+}
+EXPORT_SYMBOL(drm_rotation_simplify);
 
 /**
  * drm_plane_create_zpos_property - create mutable zpos property
  * If zpos of some planes cannot be changed (like fixed background or
  * cursor/topmost planes), driver should adjust min/max values and assign those
  * planes immutable zpos property with lower or higher values (for more
- * information, see drm_mode_create_zpos_immutable_property() function). In such
+ * information, see drm_plane_create_zpos_immutable_property() function). In such
  * case driver should also assign proper initial zpos values for all planes in
  * its plane_reset() callback, so the planes will be always sorted properly.
  *
+ * See also drm_atomic_normalize_zpos().
+ *
+ * The property exposed to userspace is called "zpos".
+ *
  * Returns:
  * Zero on success, negative errno on failure.
  */
@@ -88,7 +253,9 @@ EXPORT_SYMBOL(drm_plane_create_zpos_property);
  * support for it in drm core. Using this property driver lets userspace
  * to get the arrangement of the planes for blending operation and notifies
  * it that the hardware (or driver) doesn't support changing of the planes'
- * order.
+ * order. For mutable zpos see drm_plane_create_zpos_property().
+ *
+ * The property exposed to userspace is called "zpos".
  *
  * Returns:
  * Zero on success, negative errno on failure.
@@ -127,20 +294,6 @@ static int drm_atomic_state_zpos_cmp(const void *a, const void *b)
                return sa->plane->base.id - sb->plane->base.id;
 }
 
-/**
- * drm_atomic_helper_crtc_normalize_zpos - calculate normalized zpos values
- * @crtc: crtc with planes, which have to be considered for normalization
- * @crtc_state: new atomic state to apply
- *
- * This function checks new states of all planes assigned to given crtc and
- * calculates normalized zpos value for them. Planes are compared first by their
- * zpos values, then by plane id (if zpos equals). Plane with lowest zpos value
- * is at the bottom. The plane_state->normalized_zpos is then filled with unique
- * values from 0 to number of active planes in crtc minus one.
- *
- * RETURNS
- * Zero for success or -errno
- */
 static int drm_atomic_helper_crtc_normalize_zpos(struct drm_crtc *crtc,
                                          struct drm_crtc_state *crtc_state)
 {
@@ -198,8 +351,14 @@ done:
  * @state: atomic state of DRM device
  *
  * This function calculates normalized zpos value for all modified planes in
- * the provided atomic state of DRM device. For more information, see
- * drm_atomic_helper_crtc_normalize_zpos() function.
+ * the provided atomic state of DRM device.
+ *
+ * For every CRTC this function checks new states of all planes assigned to
+ * it and calculates normalized zpos value for these planes. Planes are compared
+ * first by their zpos values, then by plane id (if zpos is equal). The plane
+ * with lowest zpos value is at the bottom. The plane_state->normalized_zpos is
+ * then filled with unique values from 0 to number of active planes in crtc
+ * minus one.
  *
  * RETURNS
  * Zero for success or -errno
index 484046664d6c41f08eaa1efdb4bc85d52b454cbc..0ee052b7c21af76f9e172075c4b5671af018d2f0 100644 (file)
 
 #include <linux/err.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 
-#include <drm/drm_crtc.h>
-
-#include "drm/drmP.h"
+#include <drm/drm_bridge.h>
 
 /**
  * DOC: overview
index 32191513e82d040ea3756cc957115f9505606a1f..adb1dd7fde5f381afb9a0bd443f2e05312d71a5f 100644 (file)
@@ -755,7 +755,7 @@ int drm_legacy_addbufs_agp(struct drm_device *dev,
                return -EINVAL;
        }
 
-       entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
+       entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL);
        if (!entry->buflist) {
                mutex_unlock(&dev->struct_mutex);
                atomic_dec(&dev->buf_alloc);
@@ -905,14 +905,14 @@ int drm_legacy_addbufs_pci(struct drm_device *dev,
                return -EINVAL;
        }
 
-       entry->buflist = kzalloc(count * sizeof(*entry->buflist), GFP_KERNEL);
+       entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL);
        if (!entry->buflist) {
                mutex_unlock(&dev->struct_mutex);
                atomic_dec(&dev->buf_alloc);
                return -ENOMEM;
        }
 
-       entry->seglist = kzalloc(count * sizeof(*entry->seglist), GFP_KERNEL);
+       entry->seglist = kcalloc(count, sizeof(*entry->seglist), GFP_KERNEL);
        if (!entry->seglist) {
                kfree(entry->buflist);
                mutex_unlock(&dev->struct_mutex);
@@ -923,8 +923,9 @@ int drm_legacy_addbufs_pci(struct drm_device *dev,
        /* Keep the original pagelist until we know all the allocations
         * have succeeded
         */
-       temp_pagelist = kmalloc((dma->page_count + (count << page_order)) *
-                              sizeof(*dma->pagelist), GFP_KERNEL);
+       temp_pagelist = kmalloc_array(dma->page_count + (count << page_order),
+                                     sizeof(*dma->pagelist),
+                                     GFP_KERNEL);
        if (!temp_pagelist) {
                kfree(entry->buflist);
                kfree(entry->seglist);
@@ -1116,8 +1117,7 @@ static int drm_legacy_addbufs_sg(struct drm_device *dev,
                return -EINVAL;
        }
 
-       entry->buflist = kzalloc(count * sizeof(*entry->buflist),
-                               GFP_KERNEL);
+       entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL);
        if (!entry->buflist) {
                mutex_unlock(&dev->struct_mutex);
                atomic_dec(&dev->buf_alloc);
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
new file mode 100644 (file)
index 0000000..d28ffdd
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * 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_crtc.h>
+#include <drm/drm_color_mgmt.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * Color management or color space adjustments is supported through a set of 5
+ * properties on the &drm_crtc object. They are set up by calling
+ * drm_crtc_enable_color_mgmt().
+ *
+ * "DEGAMMA_LUT”:
+ *     Blob property to set the degamma lookup table (LUT) mapping pixel data
+ *     from the framebuffer before it is given to the transformation matrix.
+ *     The data is interpreted as an array of struct &drm_color_lut elements.
+ *     Hardware might choose not to use the full precision of the LUT elements
+ *     nor use all the elements of the LUT (for example the hardware might
+ *     choose to interpolate between LUT[0] and LUT[4]).
+ *
+ * “DEGAMMA_LUT_SIZE”:
+ *     Unsinged range property to give the size of the lookup table to be set
+ *     on the DEGAMMA_LUT property (the size depends on the underlying
+ *     hardware). If drivers support multiple LUT sizes then they should
+ *     publish the largest size, and sub-sample smaller sized LUTs (e.g. for
+ *     split-gamma modes) appropriately.
+ *
+ * “CTM”:
+ *     Blob property to set the current transformation matrix (CTM) apply to
+ *     pixel data after the lookup through the degamma LUT and before the
+ *     lookup through the gamma LUT. The data is interpreted as a struct
+ *     &drm_color_ctm.
+ *
+ * “GAMMA_LUT”:
+ *     Blob property to set the gamma lookup table (LUT) mapping pixel data
+ *     after the transformation matrix to data sent to the connector. The
+ *     data is interpreted as an array of struct &drm_color_lut elements.
+ *     Hardware might choose not to use the full precision of the LUT elements
+ *     nor use all the elements of the LUT (for example the hardware might
+ *     choose to interpolate between LUT[0] and LUT[4]).
+ *
+ * “GAMMA_LUT_SIZE”:
+ *     Unsigned range property to give the size of the lookup table to be set
+ *     on the GAMMA_LUT property (the size depends on the underlying hardware).
+ *     If drivers support multiple LUT sizes then they should publish the
+ *     largest size, and sub-sample smaller sized LUTs (e.g. for split-gamma
+ *     modes) appropriately.
+ *
+ * There is also support for a legacy gamma table, which is set up by calling
+ * drm_mode_crtc_set_gamma_size(). Drivers which support both should use
+ * drm_atomic_helper_legacy_gamma_set() to alias the legacy gamma ramp with the
+ * "GAMMA_LUT" property above.
+ */
+
+/**
+ * drm_crtc_enable_color_mgmt - enable color management properties
+ * @crtc: DRM CRTC
+ * @degamma_lut_size: the size of the degamma lut (before CSC)
+ * @has_ctm: whether to attach ctm_property for CSC matrix
+ * @gamma_lut_size: the size of the gamma lut (after CSC)
+ *
+ * This function lets the driver enable the color correction
+ * properties on a CRTC. This includes 3 degamma, csc and gamma
+ * properties that userspace can set and 2 size properties to inform
+ * the userspace of the lut sizes. Each of the properties are
+ * optional. The gamma and degamma properties are only attached if
+ * their size is not 0 and ctm_property is only attached if has_ctm is
+ * true.
+ */
+void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+                               uint degamma_lut_size,
+                               bool has_ctm,
+                               uint gamma_lut_size)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_mode_config *config = &dev->mode_config;
+
+       if (degamma_lut_size) {
+               drm_object_attach_property(&crtc->base,
+                                          config->degamma_lut_property, 0);
+               drm_object_attach_property(&crtc->base,
+                                          config->degamma_lut_size_property,
+                                          degamma_lut_size);
+       }
+
+       if (has_ctm)
+               drm_object_attach_property(&crtc->base,
+                                          config->ctm_property, 0);
+
+       if (gamma_lut_size) {
+               drm_object_attach_property(&crtc->base,
+                                          config->gamma_lut_property, 0);
+               drm_object_attach_property(&crtc->base,
+                                          config->gamma_lut_size_property,
+                                          gamma_lut_size);
+       }
+}
+EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
+
+/**
+ * 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
+ *
+ * Drivers which support gamma tables should set this to the supported gamma
+ * table size when initializing the CRTC. Currently the drm core only supports a
+ * fixed gamma table size.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
+                                int gamma_size)
+{
+       uint16_t *r_base, *g_base, *b_base;
+       int i;
+
+       crtc->gamma_size = gamma_size;
+
+       crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3,
+                                   GFP_KERNEL);
+       if (!crtc->gamma_store) {
+               crtc->gamma_size = 0;
+               return -ENOMEM;
+       }
+
+       r_base = crtc->gamma_store;
+       g_base = r_base + gamma_size;
+       b_base = g_base + gamma_size;
+       for (i = 0; i < gamma_size; i++) {
+               r_base[i] = i << 8;
+               g_base[i] = i << 8;
+               b_base[i] = i << 8;
+       }
+
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
+
+/**
+ * drm_mode_gamma_set_ioctl - set the gamma table
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Set the gamma table of a CRTC to the one passed in by the user. Userspace can
+ * inquire the required gamma table size through drm_mode_gamma_get_ioctl.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_gamma_set_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_crtc_lut *crtc_lut = data;
+       struct drm_crtc *crtc;
+       void *r_base, *g_base, *b_base;
+       int size;
+       int ret = 0;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       drm_modeset_lock_all(dev);
+       crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+       if (!crtc) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (crtc->funcs->gamma_set == NULL) {
+               ret = -ENOSYS;
+               goto out;
+       }
+
+       /* memcpy into gamma store */
+       if (crtc_lut->gamma_size != crtc->gamma_size) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       size = crtc_lut->gamma_size * (sizeof(uint16_t));
+       r_base = crtc->gamma_store;
+       if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       g_base = r_base + size;
+       if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       b_base = g_base + size;
+       if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
+
+out:
+       drm_modeset_unlock_all(dev);
+       return ret;
+
+}
+
+/**
+ * drm_mode_gamma_get_ioctl - get the gamma table
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Copy the current gamma table into the storage provided. This also provides
+ * the gamma table size the driver expects, which can be used to size the
+ * allocated storage.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_gamma_get_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_crtc_lut *crtc_lut = data;
+       struct drm_crtc *crtc;
+       void *r_base, *g_base, *b_base;
+       int size;
+       int ret = 0;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       drm_modeset_lock_all(dev);
+       crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+       if (!crtc) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       /* memcpy into gamma store */
+       if (crtc_lut->gamma_size != crtc->gamma_size) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       size = crtc_lut->gamma_size * (sizeof(uint16_t));
+       r_base = crtc->gamma_store;
+       if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       g_base = r_base + size;
+       if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+
+       b_base = g_base + size;
+       if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
+               ret = -EFAULT;
+               goto out;
+       }
+out:
+       drm_modeset_unlock_all(dev);
+       return ret;
+}
index 631691bae01d7f914844e2eac5b83d26e7e7da64..2d7bedf286473c20b0da3ba7bd5a3c945f0c7be6 100644 (file)
@@ -151,7 +151,11 @@ static void drm_crtc_unregister_all(struct drm_device *dev)
  * @funcs: callbacks for the new CRTC
  * @name: printf style format string for the CRTC name, or NULL for default name
  *
- * Inits a new object created as base part of a driver crtc object.
+ * Inits a new object created as base part of a driver crtc object. Drivers
+ * should use this function instead of drm_crtc_init(), which is only provided
+ * for backwards compatibility with drivers which do not yet support universal
+ * planes). For really simple hardware which has only 1 plane look at
+ * drm_simple_display_pipe_init() instead.
  *
  * Returns:
  * Zero on success, error code on failure.
@@ -251,255 +255,6 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
 }
 EXPORT_SYMBOL(drm_crtc_cleanup);
 
-static unsigned int drm_num_planes(struct drm_device *dev)
-{
-       unsigned int num = 0;
-       struct drm_plane *tmp;
-
-       drm_for_each_plane(tmp, dev) {
-               num++;
-       }
-
-       return num;
-}
-
-/**
- * drm_universal_plane_init - Initialize a new universal plane object
- * @dev: DRM device
- * @plane: plane object to init
- * @possible_crtcs: bitmask of possible CRTCs
- * @funcs: callbacks for the new plane
- * @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
- *
- * Initializes a plane object of type @type.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
-                            unsigned long possible_crtcs,
-                            const struct drm_plane_funcs *funcs,
-                            const uint32_t *formats, unsigned int format_count,
-                            enum drm_plane_type type,
-                            const char *name, ...)
-{
-       struct drm_mode_config *config = &dev->mode_config;
-       int ret;
-
-       ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
-       if (ret)
-               return ret;
-
-       drm_modeset_lock_init(&plane->mutex);
-
-       plane->base.properties = &plane->properties;
-       plane->dev = dev;
-       plane->funcs = funcs;
-       plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
-                                           GFP_KERNEL);
-       if (!plane->format_types) {
-               DRM_DEBUG_KMS("out of memory when allocating plane\n");
-               drm_mode_object_unregister(dev, &plane->base);
-               return -ENOMEM;
-       }
-
-       if (name) {
-               va_list ap;
-
-               va_start(ap, name);
-               plane->name = kvasprintf(GFP_KERNEL, name, ap);
-               va_end(ap);
-       } else {
-               plane->name = kasprintf(GFP_KERNEL, "plane-%d",
-                                       drm_num_planes(dev));
-       }
-       if (!plane->name) {
-               kfree(plane->format_types);
-               drm_mode_object_unregister(dev, &plane->base);
-               return -ENOMEM;
-       }
-
-       memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
-       plane->format_count = format_count;
-       plane->possible_crtcs = possible_crtcs;
-       plane->type = type;
-
-       list_add_tail(&plane->head, &config->plane_list);
-       plane->index = config->num_total_plane++;
-       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
-               config->num_overlay_plane++;
-
-       drm_object_attach_property(&plane->base,
-                                  config->plane_type_property,
-                                  plane->type);
-
-       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
-               drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
-               drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
-               drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
-               drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
-               drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
-               drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
-               drm_object_attach_property(&plane->base, config->prop_src_x, 0);
-               drm_object_attach_property(&plane->base, config->prop_src_y, 0);
-               drm_object_attach_property(&plane->base, config->prop_src_w, 0);
-               drm_object_attach_property(&plane->base, config->prop_src_h, 0);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_universal_plane_init);
-
-static int drm_plane_register_all(struct drm_device *dev)
-{
-       struct drm_plane *plane;
-       int ret = 0;
-
-       drm_for_each_plane(plane, dev) {
-               if (plane->funcs->late_register)
-                       ret = plane->funcs->late_register(plane);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static void drm_plane_unregister_all(struct drm_device *dev)
-{
-       struct drm_plane *plane;
-
-       drm_for_each_plane(plane, dev) {
-               if (plane->funcs->early_unregister)
-                       plane->funcs->early_unregister(plane);
-       }
-}
-
-/**
- * drm_plane_init - Initialize a legacy plane
- * @dev: DRM device
- * @plane: plane object to init
- * @possible_crtcs: bitmask of possible CRTCs
- * @funcs: callbacks for the new plane
- * @formats: array of supported formats (DRM_FORMAT\_\*)
- * @format_count: number of elements in @formats
- * @is_primary: plane type (primary vs overlay)
- *
- * Legacy API to initialize a DRM plane.
- *
- * New drivers should call drm_universal_plane_init() instead.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
-                  unsigned long possible_crtcs,
-                  const struct drm_plane_funcs *funcs,
-                  const uint32_t *formats, unsigned int format_count,
-                  bool is_primary)
-{
-       enum drm_plane_type type;
-
-       type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
-       return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
-                                       formats, format_count, type, NULL);
-}
-EXPORT_SYMBOL(drm_plane_init);
-
-/**
- * drm_plane_cleanup - Clean up the core plane usage
- * @plane: plane to cleanup
- *
- * This function cleans up @plane and removes it from the DRM mode setting
- * core. Note that the function does *not* free the plane structure itself,
- * this is the responsibility of the caller.
- */
-void drm_plane_cleanup(struct drm_plane *plane)
-{
-       struct drm_device *dev = plane->dev;
-
-       drm_modeset_lock_all(dev);
-       kfree(plane->format_types);
-       drm_mode_object_unregister(dev, &plane->base);
-
-       BUG_ON(list_empty(&plane->head));
-
-       /* Note that the plane_list is considered to be static; should we
-        * remove the drm_plane at runtime we would have to decrement all
-        * the indices on the drm_plane after us in the plane_list.
-        */
-
-       list_del(&plane->head);
-       dev->mode_config.num_total_plane--;
-       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
-               dev->mode_config.num_overlay_plane--;
-       drm_modeset_unlock_all(dev);
-
-       WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
-       if (plane->state && plane->funcs->atomic_destroy_state)
-               plane->funcs->atomic_destroy_state(plane, plane->state);
-
-       kfree(plane->name);
-
-       memset(plane, 0, sizeof(*plane));
-}
-EXPORT_SYMBOL(drm_plane_cleanup);
-
-/**
- * drm_plane_from_index - find the registered plane at an index
- * @dev: DRM device
- * @idx: index of registered plane to find for
- *
- * Given a plane index, return the registered plane from DRM device's
- * list of planes with matching index.
- */
-struct drm_plane *
-drm_plane_from_index(struct drm_device *dev, int idx)
-{
-       struct drm_plane *plane;
-
-       drm_for_each_plane(plane, dev)
-               if (idx == plane->index)
-                       return plane;
-
-       return NULL;
-}
-EXPORT_SYMBOL(drm_plane_from_index);
-
-/**
- * drm_plane_force_disable - Forcibly disable a plane
- * @plane: plane to disable
- *
- * Forces the plane to be disabled.
- *
- * Used when the plane's current framebuffer is destroyed,
- * and when restoring fbdev mode.
- */
-void drm_plane_force_disable(struct drm_plane *plane)
-{
-       int ret;
-
-       if (!plane->fb)
-               return;
-
-       plane->old_fb = plane->fb;
-       ret = plane->funcs->disable_plane(plane);
-       if (ret) {
-               DRM_ERROR("failed to disable plane with busy fb\n");
-               plane->old_fb = NULL;
-               return;
-       }
-       /* disconnect the plane from the fb and crtc: */
-       drm_framebuffer_unreference(plane->old_fb);
-       plane->old_fb = NULL;
-       plane->fb = NULL;
-       plane->crtc = NULL;
-}
-EXPORT_SYMBOL(drm_plane_force_disable);
-
 int drm_modeset_register_all(struct drm_device *dev)
 {
        int ret;
@@ -855,395 +610,58 @@ int drm_mode_getcrtc(struct drm_device *dev,
 }
 
 /**
- * drm_mode_getplane_res - enumerate all plane resources
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Construct a list of plane ids to return to the user.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_getplane_res(struct drm_device *dev, void *data,
-                         struct drm_file *file_priv)
-{
-       struct drm_mode_get_plane_res *plane_resp = data;
-       struct drm_mode_config *config;
-       struct drm_plane *plane;
-       uint32_t __user *plane_ptr;
-       int copied = 0;
-       unsigned num_planes;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       config = &dev->mode_config;
-
-       if (file_priv->universal_planes)
-               num_planes = config->num_total_plane;
-       else
-               num_planes = config->num_overlay_plane;
-
-       /*
-        * This ioctl is called twice, once to determine how much space is
-        * needed, and the 2nd time to fill it.
-        */
-       if (num_planes &&
-           (plane_resp->count_planes >= num_planes)) {
-               plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
-
-               /* Plane lists are invariant, no locking needed. */
-               drm_for_each_plane(plane, dev) {
-                       /*
-                        * Unless userspace set the 'universal planes'
-                        * capability bit, only advertise overlays.
-                        */
-                       if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
-                           !file_priv->universal_planes)
-                               continue;
-
-                       if (put_user(plane->base.id, plane_ptr + copied))
-                               return -EFAULT;
-                       copied++;
-               }
-       }
-       plane_resp->count_planes = num_planes;
-
-       return 0;
-}
-
-/**
- * drm_mode_getplane - get plane configuration
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Construct a plane configuration structure to return to the user.
+ * drm_mode_set_config_internal - helper to call ->set_config
+ * @set: modeset config to set
  *
- * Called by the user via ioctl.
+ * This is a little helper to wrap internal calls to the ->set_config driver
+ * interface. The only thing it adds is correct refcounting dance.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_getplane(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv)
+int drm_mode_set_config_internal(struct drm_mode_set *set)
 {
-       struct drm_mode_get_plane *plane_resp = data;
-       struct drm_plane *plane;
-       uint32_t __user *format_ptr;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       plane = drm_plane_find(dev, plane_resp->plane_id);
-       if (!plane)
-               return -ENOENT;
-
-       drm_modeset_lock(&plane->mutex, NULL);
-       if (plane->crtc)
-               plane_resp->crtc_id = plane->crtc->base.id;
-       else
-               plane_resp->crtc_id = 0;
-
-       if (plane->fb)
-               plane_resp->fb_id = plane->fb->base.id;
-       else
-               plane_resp->fb_id = 0;
-       drm_modeset_unlock(&plane->mutex);
-
-       plane_resp->plane_id = plane->base.id;
-       plane_resp->possible_crtcs = plane->possible_crtcs;
-       plane_resp->gamma_size = 0;
+       struct drm_crtc *crtc = set->crtc;
+       struct drm_framebuffer *fb;
+       struct drm_crtc *tmp;
+       int ret;
 
        /*
-        * This ioctl is called twice, once to determine how much space is
-        * needed, and the 2nd time to fill it.
+        * NOTE: ->set_config can also disable other crtcs (if we steal all
+        * connectors from it), hence we need to refcount the fbs across all
+        * crtcs. Atomic modeset will have saner semantics ...
         */
-       if (plane->format_count &&
-           (plane_resp->count_format_types >= plane->format_count)) {
-               format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
-               if (copy_to_user(format_ptr,
-                                plane->format_types,
-                                sizeof(uint32_t) * plane->format_count)) {
-                       return -EFAULT;
-               }
-       }
-       plane_resp->count_format_types = plane->format_count;
-
-       return 0;
-}
-
-/**
- * drm_plane_check_pixel_format - Check if the plane supports the pixel format
- * @plane: plane to check for format support
- * @format: the pixel format
- *
- * Returns:
- * Zero of @plane has @format in its list of supported pixel formats, -EINVAL
- * otherwise.
- */
-int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
-{
-       unsigned int i;
-
-       for (i = 0; i < plane->format_count; i++) {
-               if (format == plane->format_types[i])
-                       return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int check_src_coords(uint32_t src_x, uint32_t src_y,
-                           uint32_t src_w, uint32_t src_h,
-                           const struct drm_framebuffer *fb)
-{
-       unsigned int fb_width, fb_height;
-
-       fb_width = fb->width << 16;
-       fb_height = fb->height << 16;
-
-       /* Make sure source coordinates are inside the fb. */
-       if (src_w > fb_width ||
-           src_x > fb_width - src_w ||
-           src_h > fb_height ||
-           src_y > fb_height - src_h) {
-               DRM_DEBUG_KMS("Invalid source coordinates "
-                             "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
-                             src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
-                             src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
-                             src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
-                             src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
-               return -ENOSPC;
-       }
-
-       return 0;
-}
-
-/*
- * setplane_internal - setplane handler for internal callers
- *
- * Note that we assume an extra reference has already been taken on fb.  If the
- * update fails, this reference will be dropped before return; if it succeeds,
- * the previous framebuffer (if any) will be unreferenced instead.
- *
- * src_{x,y,w,h} are provided in 16.16 fixed point format
- */
-static int __setplane_internal(struct drm_plane *plane,
-                              struct drm_crtc *crtc,
-                              struct drm_framebuffer *fb,
-                              int32_t crtc_x, int32_t crtc_y,
-                              uint32_t crtc_w, uint32_t crtc_h,
-                              /* src_{x,y,w,h} values are 16.16 fixed point */
-                              uint32_t src_x, uint32_t src_y,
-                              uint32_t src_w, uint32_t src_h)
-{
-       int ret = 0;
-
-       /* No fb means shut it down */
-       if (!fb) {
-               plane->old_fb = plane->fb;
-               ret = plane->funcs->disable_plane(plane);
-               if (!ret) {
-                       plane->crtc = NULL;
-                       plane->fb = NULL;
-               } else {
-                       plane->old_fb = NULL;
-               }
-               goto out;
-       }
-
-       /* Check whether this plane is usable on this CRTC */
-       if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
-               DRM_DEBUG_KMS("Invalid crtc for plane\n");
-               ret = -EINVAL;
-               goto out;
-       }
+       drm_for_each_crtc(tmp, crtc->dev)
+               tmp->primary->old_fb = tmp->primary->fb;
 
-       /* Check whether this plane supports the fb pixel format. */
-       ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
-       if (ret) {
-               char *format_name = drm_get_format_name(fb->pixel_format);
-               DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
-               kfree(format_name);
-               goto out;
-       }
+       fb = set->fb;
 
-       /* Give drivers some help against integer overflows */
-       if (crtc_w > INT_MAX ||
-           crtc_x > INT_MAX - (int32_t) crtc_w ||
-           crtc_h > INT_MAX ||
-           crtc_y > INT_MAX - (int32_t) crtc_h) {
-               DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
-                             crtc_w, crtc_h, crtc_x, crtc_y);
-               ret = -ERANGE;
-               goto out;
+       ret = crtc->funcs->set_config(set);
+       if (ret == 0) {
+               crtc->primary->crtc = crtc;
+               crtc->primary->fb = fb;
        }
 
-       ret = check_src_coords(src_x, src_y, src_w, src_h, fb);
-       if (ret)
-               goto out;
-
-       plane->old_fb = plane->fb;
-       ret = plane->funcs->update_plane(plane, crtc, fb,
-                                        crtc_x, crtc_y, crtc_w, crtc_h,
-                                        src_x, src_y, src_w, src_h);
-       if (!ret) {
-               plane->crtc = crtc;
-               plane->fb = fb;
-               fb = NULL;
-       } else {
-               plane->old_fb = NULL;
+       drm_for_each_crtc(tmp, crtc->dev) {
+               if (tmp->primary->fb)
+                       drm_framebuffer_reference(tmp->primary->fb);
+               if (tmp->primary->old_fb)
+                       drm_framebuffer_unreference(tmp->primary->old_fb);
+               tmp->primary->old_fb = NULL;
        }
 
-out:
-       if (fb)
-               drm_framebuffer_unreference(fb);
-       if (plane->old_fb)
-               drm_framebuffer_unreference(plane->old_fb);
-       plane->old_fb = NULL;
-
-       return ret;
-}
-
-static int setplane_internal(struct drm_plane *plane,
-                            struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb,
-                            int32_t crtc_x, int32_t crtc_y,
-                            uint32_t crtc_w, uint32_t crtc_h,
-                            /* src_{x,y,w,h} values are 16.16 fixed point */
-                            uint32_t src_x, uint32_t src_y,
-                            uint32_t src_w, uint32_t src_h)
-{
-       int ret;
-
-       drm_modeset_lock_all(plane->dev);
-       ret = __setplane_internal(plane, crtc, fb,
-                                 crtc_x, crtc_y, crtc_w, crtc_h,
-                                 src_x, src_y, src_w, src_h);
-       drm_modeset_unlock_all(plane->dev);
-
        return ret;
 }
+EXPORT_SYMBOL(drm_mode_set_config_internal);
 
 /**
- * drm_mode_setplane - configure a plane's configuration
- * @dev: DRM device
- * @data: ioctl data*
- * @file_priv: DRM file info
- *
- * Set plane configuration, including placement, fb, scaling, and other factors.
- * Or pass a NULL fb to disable (planes may be disabled without providing a
- * valid crtc).
+ * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode
+ * @mode: mode to query
+ * @hdisplay: hdisplay value to fill in
+ * @vdisplay: vdisplay value to fill in
  *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_setplane(struct drm_device *dev, void *data,
-                     struct drm_file *file_priv)
-{
-       struct drm_mode_set_plane *plane_req = data;
-       struct drm_plane *plane;
-       struct drm_crtc *crtc = NULL;
-       struct drm_framebuffer *fb = NULL;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       /*
-        * First, find the plane, crtc, and fb objects.  If not available,
-        * we don't bother to call the driver.
-        */
-       plane = drm_plane_find(dev, plane_req->plane_id);
-       if (!plane) {
-               DRM_DEBUG_KMS("Unknown plane ID %d\n",
-                             plane_req->plane_id);
-               return -ENOENT;
-       }
-
-       if (plane_req->fb_id) {
-               fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
-               if (!fb) {
-                       DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
-                                     plane_req->fb_id);
-                       return -ENOENT;
-               }
-
-               crtc = drm_crtc_find(dev, plane_req->crtc_id);
-               if (!crtc) {
-                       DRM_DEBUG_KMS("Unknown crtc ID %d\n",
-                                     plane_req->crtc_id);
-                       return -ENOENT;
-               }
-       }
-
-       /*
-        * setplane_internal will take care of deref'ing either the old or new
-        * framebuffer depending on success.
-        */
-       return setplane_internal(plane, crtc, fb,
-                                plane_req->crtc_x, plane_req->crtc_y,
-                                plane_req->crtc_w, plane_req->crtc_h,
-                                plane_req->src_x, plane_req->src_y,
-                                plane_req->src_w, plane_req->src_h);
-}
-
-/**
- * drm_mode_set_config_internal - helper to call ->set_config
- * @set: modeset config to set
- *
- * This is a little helper to wrap internal calls to the ->set_config driver
- * interface. The only thing it adds is correct refcounting dance.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_set_config_internal(struct drm_mode_set *set)
-{
-       struct drm_crtc *crtc = set->crtc;
-       struct drm_framebuffer *fb;
-       struct drm_crtc *tmp;
-       int ret;
-
-       /*
-        * NOTE: ->set_config can also disable other crtcs (if we steal all
-        * connectors from it), hence we need to refcount the fbs across all
-        * crtcs. Atomic modeset will have saner semantics ...
-        */
-       drm_for_each_crtc(tmp, crtc->dev)
-               tmp->primary->old_fb = tmp->primary->fb;
-
-       fb = set->fb;
-
-       ret = crtc->funcs->set_config(set);
-       if (ret == 0) {
-               crtc->primary->crtc = crtc;
-               crtc->primary->fb = fb;
-       }
-
-       drm_for_each_crtc(tmp, crtc->dev) {
-               if (tmp->primary->fb)
-                       drm_framebuffer_reference(tmp->primary->fb);
-               if (tmp->primary->old_fb)
-                       drm_framebuffer_unreference(tmp->primary->old_fb);
-               tmp->primary->old_fb = NULL;
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_mode_set_config_internal);
-
-/**
- * drm_crtc_get_hv_timing - Fetches hdisplay/vdisplay for given mode
- * @mode: mode to query
- * @hdisplay: hdisplay value to fill in
- * @vdisplay: vdisplay value to fill in
- *
- * The vdisplay value will be doubled if the specified mode is a stereo mode of
- * the appropriate layout.
+ * The vdisplay value will be doubled if the specified mode is a stereo mode of
+ * the appropriate layout.
  */
 void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
                            int *hdisplay, int *vdisplay)
@@ -1251,807 +669,236 @@ void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
        struct drm_display_mode adjusted;
 
        drm_mode_copy(&adjusted, mode);
-       drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
-       *hdisplay = adjusted.crtc_hdisplay;
-       *vdisplay = adjusted.crtc_vdisplay;
-}
-EXPORT_SYMBOL(drm_crtc_get_hv_timing);
-
-/**
- * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
- *     CRTC viewport
- * @crtc: CRTC that framebuffer will be displayed on
- * @x: x panning
- * @y: y panning
- * @mode: mode that framebuffer will be displayed under
- * @fb: framebuffer to check size of
- */
-int drm_crtc_check_viewport(const struct drm_crtc *crtc,
-                           int x, int y,
-                           const struct drm_display_mode *mode,
-                           const struct drm_framebuffer *fb)
-
-{
-       int hdisplay, vdisplay;
-
-       drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
-
-       if (crtc->state &&
-           crtc->primary->state->rotation & (DRM_ROTATE_90 |
-                                             DRM_ROTATE_270))
-               swap(hdisplay, vdisplay);
-
-       return check_src_coords(x << 16, y << 16,
-                               hdisplay << 16, vdisplay << 16, fb);
-}
-EXPORT_SYMBOL(drm_crtc_check_viewport);
-
-/**
- * drm_mode_setcrtc - set CRTC configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Build a new CRTC configuration based on user request.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_setcrtc(struct drm_device *dev, void *data,
-                    struct drm_file *file_priv)
-{
-       struct drm_mode_config *config = &dev->mode_config;
-       struct drm_mode_crtc *crtc_req = data;
-       struct drm_crtc *crtc;
-       struct drm_connector **connector_set = NULL, *connector;
-       struct drm_framebuffer *fb = NULL;
-       struct drm_display_mode *mode = NULL;
-       struct drm_mode_set set;
-       uint32_t __user *set_connectors_ptr;
-       int ret;
-       int i;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       /*
-        * Universal plane src offsets are only 16.16, prevent havoc for
-        * drivers using universal plane code internally.
-        */
-       if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
-               return -ERANGE;
-
-       drm_modeset_lock_all(dev);
-       crtc = drm_crtc_find(dev, crtc_req->crtc_id);
-       if (!crtc) {
-               DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
-               ret = -ENOENT;
-               goto out;
-       }
-       DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
-
-       if (crtc_req->mode_valid) {
-               /* If we have a mode we need a framebuffer. */
-               /* If we pass -1, set the mode with the currently bound fb */
-               if (crtc_req->fb_id == -1) {
-                       if (!crtc->primary->fb) {
-                               DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
-                               ret = -EINVAL;
-                               goto out;
-                       }
-                       fb = crtc->primary->fb;
-                       /* Make refcounting symmetric with the lookup path. */
-                       drm_framebuffer_reference(fb);
-               } else {
-                       fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
-                       if (!fb) {
-                               DRM_DEBUG_KMS("Unknown FB ID%d\n",
-                                               crtc_req->fb_id);
-                               ret = -ENOENT;
-                               goto out;
-                       }
-               }
-
-               mode = drm_mode_create(dev);
-               if (!mode) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               ret = drm_mode_convert_umode(mode, &crtc_req->mode);
-               if (ret) {
-                       DRM_DEBUG_KMS("Invalid mode\n");
-                       goto out;
-               }
-
-               /*
-                * Check whether the primary plane supports the fb pixel format.
-                * Drivers not implementing the universal planes API use a
-                * default formats list provided by the DRM core which doesn't
-                * match real hardware capabilities. Skip the check in that
-                * case.
-                */
-               if (!crtc->primary->format_default) {
-                       ret = drm_plane_check_pixel_format(crtc->primary,
-                                                          fb->pixel_format);
-                       if (ret) {
-                               char *format_name = drm_get_format_name(fb->pixel_format);
-                               DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
-                               kfree(format_name);
-                               goto out;
-                       }
-               }
-
-               ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
-                                             mode, fb);
-               if (ret)
-                       goto out;
-
-       }
-
-       if (crtc_req->count_connectors == 0 && mode) {
-               DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
-               DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
-                         crtc_req->count_connectors);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       if (crtc_req->count_connectors > 0) {
-               u32 out_id;
-
-               /* Avoid unbounded kernel memory allocation */
-               if (crtc_req->count_connectors > config->num_connector) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               connector_set = kmalloc_array(crtc_req->count_connectors,
-                                             sizeof(struct drm_connector *),
-                                             GFP_KERNEL);
-               if (!connector_set) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-
-               for (i = 0; i < crtc_req->count_connectors; i++) {
-                       connector_set[i] = NULL;
-                       set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
-                       if (get_user(out_id, &set_connectors_ptr[i])) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-
-                       connector = drm_connector_lookup(dev, out_id);
-                       if (!connector) {
-                               DRM_DEBUG_KMS("Connector id %d unknown\n",
-                                               out_id);
-                               ret = -ENOENT;
-                               goto out;
-                       }
-                       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
-                                       connector->base.id,
-                                       connector->name);
-
-                       connector_set[i] = connector;
-               }
-       }
-
-       set.crtc = crtc;
-       set.x = crtc_req->x;
-       set.y = crtc_req->y;
-       set.mode = mode;
-       set.connectors = connector_set;
-       set.num_connectors = crtc_req->count_connectors;
-       set.fb = fb;
-       ret = drm_mode_set_config_internal(&set);
-
-out:
-       if (fb)
-               drm_framebuffer_unreference(fb);
-
-       if (connector_set) {
-               for (i = 0; i < crtc_req->count_connectors; i++) {
-                       if (connector_set[i])
-                               drm_connector_unreference(connector_set[i]);
-               }
-       }
-       kfree(connector_set);
-       drm_mode_destroy(dev, mode);
-       drm_modeset_unlock_all(dev);
-       return ret;
-}
-
-/**
- * drm_mode_cursor_universal - translate legacy cursor ioctl call into a
- *     universal plane handler call
- * @crtc: crtc to update cursor for
- * @req: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Legacy cursor ioctl's work directly with driver buffer handles.  To
- * translate legacy ioctl calls into universal plane handler calls, we need to
- * wrap the native buffer handle in a drm_framebuffer.
- *
- * Note that we assume any handle passed to the legacy ioctls was a 32-bit ARGB
- * buffer with a pitch of 4*width; the universal plane interface should be used
- * directly in cases where the hardware can support other buffer settings and
- * userspace wants to make use of these capabilities.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-static int drm_mode_cursor_universal(struct drm_crtc *crtc,
-                                    struct drm_mode_cursor2 *req,
-                                    struct drm_file *file_priv)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_framebuffer *fb = NULL;
-       struct drm_mode_fb_cmd2 fbreq = {
-               .width = req->width,
-               .height = req->height,
-               .pixel_format = DRM_FORMAT_ARGB8888,
-               .pitches = { req->width * 4 },
-               .handles = { req->handle },
-       };
-       int32_t crtc_x, crtc_y;
-       uint32_t crtc_w = 0, crtc_h = 0;
-       uint32_t src_w = 0, src_h = 0;
-       int ret = 0;
-
-       BUG_ON(!crtc->cursor);
-       WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
-
-       /*
-        * Obtain fb we'll be using (either new or existing) and take an extra
-        * reference to it if fb != null.  setplane will take care of dropping
-        * the reference if the plane update fails.
-        */
-       if (req->flags & DRM_MODE_CURSOR_BO) {
-               if (req->handle) {
-                       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);
-                       }
-                       fb->hot_x = req->hot_x;
-                       fb->hot_y = req->hot_y;
-               } else {
-                       fb = NULL;
-               }
-       } else {
-               fb = crtc->cursor->fb;
-               if (fb)
-                       drm_framebuffer_reference(fb);
-       }
-
-       if (req->flags & DRM_MODE_CURSOR_MOVE) {
-               crtc_x = req->x;
-               crtc_y = req->y;
-       } else {
-               crtc_x = crtc->cursor_x;
-               crtc_y = crtc->cursor_y;
-       }
-
-       if (fb) {
-               crtc_w = fb->width;
-               crtc_h = fb->height;
-               src_w = fb->width << 16;
-               src_h = fb->height << 16;
-       }
-
-       /*
-        * setplane_internal will take care of deref'ing either the old or new
-        * framebuffer depending on success.
-        */
-       ret = __setplane_internal(crtc->cursor, crtc, fb,
-                               crtc_x, crtc_y, crtc_w, crtc_h,
-                               0, 0, src_w, src_h);
-
-       /* Update successful; save new cursor position, if necessary */
-       if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
-               crtc->cursor_x = req->x;
-               crtc->cursor_y = req->y;
-       }
-
-       return ret;
-}
-
-static int drm_mode_cursor_common(struct drm_device *dev,
-                                 struct drm_mode_cursor2 *req,
-                                 struct drm_file *file_priv)
-{
-       struct drm_crtc *crtc;
-       int ret = 0;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
-               return -EINVAL;
-
-       crtc = drm_crtc_find(dev, req->crtc_id);
-       if (!crtc) {
-               DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
-               return -ENOENT;
-       }
-
-       /*
-        * If this crtc has a universal cursor plane, call that plane's update
-        * handler rather than using legacy cursor handlers.
-        */
-       drm_modeset_lock_crtc(crtc, crtc->cursor);
-       if (crtc->cursor) {
-               ret = drm_mode_cursor_universal(crtc, req, file_priv);
-               goto out;
-       }
-
-       if (req->flags & DRM_MODE_CURSOR_BO) {
-               if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
-                       ret = -ENXIO;
-                       goto out;
-               }
-               /* Turns off the cursor if handle is 0 */
-               if (crtc->funcs->cursor_set2)
-                       ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
-                                                     req->width, req->height, req->hot_x, req->hot_y);
-               else
-                       ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
-                                                     req->width, req->height);
-       }
-
-       if (req->flags & DRM_MODE_CURSOR_MOVE) {
-               if (crtc->funcs->cursor_move) {
-                       ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
-               } else {
-                       ret = -EFAULT;
-                       goto out;
-               }
-       }
-out:
-       drm_modeset_unlock_crtc(crtc);
-
-       return ret;
-
-}
-
-
-/**
- * drm_mode_cursor_ioctl - set CRTC's cursor configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Set the cursor configuration based on user request.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_cursor_ioctl(struct drm_device *dev,
-                         void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_cursor *req = data;
-       struct drm_mode_cursor2 new_req;
-
-       memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
-       new_req.hot_x = new_req.hot_y = 0;
-
-       return drm_mode_cursor_common(dev, &new_req, file_priv);
-}
-
-/**
- * drm_mode_cursor2_ioctl - set CRTC's cursor configuration
- * @dev: drm device for the ioctl
- * @data: data pointer for the ioctl
- * @file_priv: drm file for the ioctl call
- *
- * Set the cursor configuration based on user request. This implements the 2nd
- * version of the cursor ioctl, which allows userspace to additionally specify
- * the hotspot of the pointer.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_cursor2_ioctl(struct drm_device *dev,
-                          void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_cursor2 *req = data;
-
-       return drm_mode_cursor_common(dev, req, file_priv);
-}
-
-int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
-                              struct drm_property *property,
-                              uint64_t value)
-{
-       int ret = -EINVAL;
-       struct drm_crtc *crtc = obj_to_crtc(obj);
-
-       if (crtc->funcs->set_property)
-               ret = crtc->funcs->set_property(crtc, property, value);
-       if (!ret)
-               drm_object_property_set_value(obj, property, value);
-
-       return ret;
-}
-
-/**
- * drm_mode_plane_set_obj_prop - set the value of a property
- * @plane: drm plane object to set property value for
- * @property: property to set
- * @value: value the property should be set to
- *
- * This functions sets a given property on a given plane object. This function
- * calls the driver's ->set_property callback and changes the software state of
- * the property if the callback succeeds.
- *
- * Returns:
- * Zero on success, error code on failure.
- */
-int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
-                               struct drm_property *property,
-                               uint64_t value)
-{
-       int ret = -EINVAL;
-       struct drm_mode_object *obj = &plane->base;
-
-       if (plane->funcs->set_property)
-               ret = plane->funcs->set_property(plane, property, value);
-       if (!ret)
-               drm_object_property_set_value(obj, property, value);
-
-       return ret;
-}
-EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
-
-/**
- * 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
- *
- * Drivers which support gamma tables should set this to the supported gamma
- * table size when initializing the CRTC. Currently the drm core only supports a
- * fixed gamma table size.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
-                                int gamma_size)
-{
-       uint16_t *r_base, *g_base, *b_base;
-       int i;
-
-       crtc->gamma_size = gamma_size;
-
-       crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3,
-                                   GFP_KERNEL);
-       if (!crtc->gamma_store) {
-               crtc->gamma_size = 0;
-               return -ENOMEM;
-       }
-
-       r_base = crtc->gamma_store;
-       g_base = r_base + gamma_size;
-       b_base = g_base + gamma_size;
-       for (i = 0; i < gamma_size; i++) {
-               r_base[i] = i << 8;
-               g_base[i] = i << 8;
-               b_base[i] = i << 8;
-       }
-
-
-       return 0;
-}
-EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
-
-/**
- * drm_mode_gamma_set_ioctl - set the gamma table
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Set the gamma table of a CRTC to the one passed in by the user. Userspace can
- * inquire the required gamma table size through drm_mode_gamma_get_ioctl.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_gamma_set_ioctl(struct drm_device *dev,
-                            void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_crtc_lut *crtc_lut = data;
-       struct drm_crtc *crtc;
-       void *r_base, *g_base, *b_base;
-       int size;
-       int ret = 0;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-
-       drm_modeset_lock_all(dev);
-       crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
-       if (!crtc) {
-               ret = -ENOENT;
-               goto out;
-       }
-
-       if (crtc->funcs->gamma_set == NULL) {
-               ret = -ENOSYS;
-               goto out;
-       }
-
-       /* memcpy into gamma store */
-       if (crtc_lut->gamma_size != crtc->gamma_size) {
-               ret = -EINVAL;
-               goto out;
-       }
-
-       size = crtc_lut->gamma_size * (sizeof(uint16_t));
-       r_base = crtc->gamma_store;
-       if (copy_from_user(r_base, (void __user *)(unsigned long)crtc_lut->red, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       g_base = r_base + size;
-       if (copy_from_user(g_base, (void __user *)(unsigned long)crtc_lut->green, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       b_base = g_base + size;
-       if (copy_from_user(b_base, (void __user *)(unsigned long)crtc_lut->blue, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-
-       ret = crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, crtc->gamma_size);
-
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
-
-}
-
-/**
- * drm_mode_gamma_get_ioctl - get the gamma table
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
- *
- * Copy the current gamma table into the storage provided. This also provides
- * the gamma table size the driver expects, which can be used to size the
- * allocated storage.
- *
- * Called by the user via ioctl.
- *
- * Returns:
- * Zero on success, negative errno on failure.
- */
-int drm_mode_gamma_get_ioctl(struct drm_device *dev,
-                            void *data, struct drm_file *file_priv)
-{
-       struct drm_mode_crtc_lut *crtc_lut = data;
-       struct drm_crtc *crtc;
-       void *r_base, *g_base, *b_base;
-       int size;
-       int ret = 0;
-
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
+       drm_mode_set_crtcinfo(&adjusted, CRTC_STEREO_DOUBLE_ONLY);
+       *hdisplay = adjusted.crtc_hdisplay;
+       *vdisplay = adjusted.crtc_vdisplay;
+}
+EXPORT_SYMBOL(drm_crtc_get_hv_timing);
 
-       drm_modeset_lock_all(dev);
-       crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
-       if (!crtc) {
-               ret = -ENOENT;
-               goto out;
-       }
+/**
+ * drm_crtc_check_viewport - Checks that a framebuffer is big enough for the
+ *     CRTC viewport
+ * @crtc: CRTC that framebuffer will be displayed on
+ * @x: x panning
+ * @y: y panning
+ * @mode: mode that framebuffer will be displayed under
+ * @fb: framebuffer to check size of
+ */
+int drm_crtc_check_viewport(const struct drm_crtc *crtc,
+                           int x, int y,
+                           const struct drm_display_mode *mode,
+                           const struct drm_framebuffer *fb)
 
-       /* memcpy into gamma store */
-       if (crtc_lut->gamma_size != crtc->gamma_size) {
-               ret = -EINVAL;
-               goto out;
-       }
+{
+       int hdisplay, vdisplay;
 
-       size = crtc_lut->gamma_size * (sizeof(uint16_t));
-       r_base = crtc->gamma_store;
-       if (copy_to_user((void __user *)(unsigned long)crtc_lut->red, r_base, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
+       drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
 
-       g_base = r_base + size;
-       if (copy_to_user((void __user *)(unsigned long)crtc_lut->green, g_base, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
+       if (crtc->state &&
+           crtc->primary->state->rotation & (DRM_ROTATE_90 |
+                                             DRM_ROTATE_270))
+               swap(hdisplay, vdisplay);
 
-       b_base = g_base + size;
-       if (copy_to_user((void __user *)(unsigned long)crtc_lut->blue, b_base, size)) {
-               ret = -EFAULT;
-               goto out;
-       }
-out:
-       drm_modeset_unlock_all(dev);
-       return ret;
+       return drm_framebuffer_check_src_coords(x << 16, y << 16,
+                                               hdisplay << 16, vdisplay << 16,
+                                               fb);
 }
+EXPORT_SYMBOL(drm_crtc_check_viewport);
 
 /**
- * drm_mode_page_flip_ioctl - schedule an asynchronous fb update
- * @dev: DRM device
- * @data: ioctl data
- * @file_priv: DRM file info
+ * drm_mode_setcrtc - set CRTC configuration
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
  *
- * This schedules an asynchronous update on a given CRTC, called page flip.
- * Optionally a drm event is generated to signal the completion of the event.
- * Generic drivers cannot assume that a pageflip with changed framebuffer
- * properties (including driver specific metadata like tiling layout) will work,
- * but some drivers support e.g. pixel format changes through the pageflip
- * ioctl.
+ * Build a new CRTC configuration based on user request.
  *
  * Called by the user via ioctl.
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int drm_mode_page_flip_ioctl(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)
 {
-       struct drm_mode_crtc_page_flip_target *page_flip = data;
+       struct drm_mode_config *config = &dev->mode_config;
+       struct drm_mode_crtc *crtc_req = data;
        struct drm_crtc *crtc;
+       struct drm_connector **connector_set = NULL, *connector;
        struct drm_framebuffer *fb = NULL;
-       struct drm_pending_vblank_event *e = NULL;
-       u32 target_vblank = page_flip->sequence;
-       int ret = -EINVAL;
-
-       if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
-               return -EINVAL;
+       struct drm_display_mode *mode = NULL;
+       struct drm_mode_set set;
+       uint32_t __user *set_connectors_ptr;
+       int ret;
+       int i;
 
-       if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
-        * can be specified
+       /*
+        * Universal plane src offsets are only 16.16, prevent havoc for
+        * drivers using universal plane code internally.
         */
-       if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
-               return -EINVAL;
-
-       if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
-               return -EINVAL;
+       if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
+               return -ERANGE;
 
-       crtc = drm_crtc_find(dev, page_flip->crtc_id);
-       if (!crtc)
-               return -ENOENT;
+       drm_modeset_lock_all(dev);
+       crtc = drm_crtc_find(dev, crtc_req->crtc_id);
+       if (!crtc) {
+               DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
+               ret = -ENOENT;
+               goto out;
+       }
+       DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name);
 
-       if (crtc->funcs->page_flip_target) {
-               u32 current_vblank;
-               int r;
+       if (crtc_req->mode_valid) {
+               /* If we have a mode we need a framebuffer. */
+               /* If we pass -1, set the mode with the currently bound fb */
+               if (crtc_req->fb_id == -1) {
+                       if (!crtc->primary->fb) {
+                               DRM_DEBUG_KMS("CRTC doesn't have current FB\n");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+                       fb = crtc->primary->fb;
+                       /* Make refcounting symmetric with the lookup path. */
+                       drm_framebuffer_reference(fb);
+               } else {
+                       fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
+                       if (!fb) {
+                               DRM_DEBUG_KMS("Unknown FB ID%d\n",
+                                               crtc_req->fb_id);
+                               ret = -ENOENT;
+                               goto out;
+                       }
+               }
 
-               r = drm_crtc_vblank_get(crtc);
-               if (r)
-                       return r;
+               mode = drm_mode_create(dev);
+               if (!mode) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
 
-               current_vblank = drm_crtc_vblank_count(crtc);
+               ret = drm_mode_convert_umode(mode, &crtc_req->mode);
+               if (ret) {
+                       DRM_DEBUG_KMS("Invalid mode\n");
+                       goto out;
+               }
 
-               switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
-               case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
-                       if ((int)(target_vblank - current_vblank) > 1) {
-                               DRM_DEBUG("Invalid absolute flip target %u, "
-                                         "must be <= %u\n", target_vblank,
-                                         current_vblank + 1);
-                               drm_crtc_vblank_put(crtc);
-                               return -EINVAL;
-                       }
-                       break;
-               case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
-                       if (target_vblank != 0 && target_vblank != 1) {
-                               DRM_DEBUG("Invalid relative flip target %u, "
-                                         "must be 0 or 1\n", target_vblank);
-                               drm_crtc_vblank_put(crtc);
-                               return -EINVAL;
+               /*
+                * Check whether the primary plane supports the fb pixel format.
+                * Drivers not implementing the universal planes API use a
+                * default formats list provided by the DRM core which doesn't
+                * match real hardware capabilities. Skip the check in that
+                * case.
+                */
+               if (!crtc->primary->format_default) {
+                       ret = drm_plane_check_pixel_format(crtc->primary,
+                                                          fb->pixel_format);
+                       if (ret) {
+                               char *format_name = drm_get_format_name(fb->pixel_format);
+                               DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
+                               kfree(format_name);
+                               goto out;
                        }
-                       target_vblank += current_vblank;
-                       break;
-               default:
-                       target_vblank = current_vblank +
-                               !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
-                       break;
                }
-       } else if (crtc->funcs->page_flip == NULL ||
-                  (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
-               return -EINVAL;
-       }
 
-       drm_modeset_lock_crtc(crtc, crtc->primary);
-       if (crtc->primary->fb == NULL) {
-               /* The framebuffer is currently unbound, presumably
-                * due to a hotplug event, that userspace has not
-                * yet discovered.
-                */
-               ret = -EBUSY;
-               goto out;
-       }
+               ret = drm_crtc_check_viewport(crtc, crtc_req->x, crtc_req->y,
+                                             mode, fb);
+               if (ret)
+                       goto out;
 
-       fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
-       if (!fb) {
-               ret = -ENOENT;
-               goto out;
        }
 
-       if (crtc->state) {
-               const struct drm_plane_state *state = crtc->primary->state;
-
-               ret = check_src_coords(state->src_x, state->src_y,
-                                      state->src_w, state->src_h, fb);
-       } else {
-               ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
-       }
-       if (ret)
+       if (crtc_req->count_connectors == 0 && mode) {
+               DRM_DEBUG_KMS("Count connectors is 0 but mode set\n");
+               ret = -EINVAL;
                goto out;
+       }
 
-       if (crtc->primary->fb->pixel_format != fb->pixel_format) {
-               DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
+       if (crtc_req->count_connectors > 0 && (!mode || !fb)) {
+               DRM_DEBUG_KMS("Count connectors is %d but no mode or fb set\n",
+                         crtc_req->count_connectors);
                ret = -EINVAL;
                goto out;
        }
 
-       if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
-               e = kzalloc(sizeof *e, GFP_KERNEL);
-               if (!e) {
-                       ret = -ENOMEM;
+       if (crtc_req->count_connectors > 0) {
+               u32 out_id;
+
+               /* Avoid unbounded kernel memory allocation */
+               if (crtc_req->count_connectors > config->num_connector) {
+                       ret = -EINVAL;
                        goto out;
                }
-               e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
-               e->event.base.length = sizeof(e->event);
-               e->event.user_data = page_flip->user_data;
-               ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
-               if (ret) {
-                       kfree(e);
+
+               connector_set = kmalloc_array(crtc_req->count_connectors,
+                                             sizeof(struct drm_connector *),
+                                             GFP_KERNEL);
+               if (!connector_set) {
+                       ret = -ENOMEM;
                        goto out;
                }
-       }
 
-       crtc->primary->old_fb = crtc->primary->fb;
-       if (crtc->funcs->page_flip_target)
-               ret = crtc->funcs->page_flip_target(crtc, fb, e,
-                                                   page_flip->flags,
-                                                   target_vblank);
-       else
-               ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
-       if (ret) {
-               if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
-                       drm_event_cancel_free(dev, &e->base);
-               /* Keep the old fb, don't unref it. */
-               crtc->primary->old_fb = NULL;
-       } else {
-               crtc->primary->fb = fb;
-               /* Unref only the old framebuffer. */
-               fb = NULL;
+               for (i = 0; i < crtc_req->count_connectors; i++) {
+                       connector_set[i] = NULL;
+                       set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
+                       if (get_user(out_id, &set_connectors_ptr[i])) {
+                               ret = -EFAULT;
+                               goto out;
+                       }
+
+                       connector = drm_connector_lookup(dev, out_id);
+                       if (!connector) {
+                               DRM_DEBUG_KMS("Connector id %d unknown\n",
+                                               out_id);
+                               ret = -ENOENT;
+                               goto out;
+                       }
+                       DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+                                       connector->base.id,
+                                       connector->name);
+
+                       connector_set[i] = connector;
+               }
        }
 
+       set.crtc = crtc;
+       set.x = crtc_req->x;
+       set.y = crtc_req->y;
+       set.mode = mode;
+       set.connectors = connector_set;
+       set.num_connectors = crtc_req->count_connectors;
+       set.fb = fb;
+       ret = drm_mode_set_config_internal(&set);
+
 out:
-       if (ret && crtc->funcs->page_flip_target)
-               drm_crtc_vblank_put(crtc);
        if (fb)
                drm_framebuffer_unreference(fb);
-       if (crtc->primary->old_fb)
-               drm_framebuffer_unreference(crtc->primary->old_fb);
-       crtc->primary->old_fb = NULL;
-       drm_modeset_unlock_crtc(crtc);
+
+       if (connector_set) {
+               for (i = 0; i < crtc_req->count_connectors; i++) {
+                       if (connector_set[i])
+                               drm_connector_unreference(connector_set[i]);
+               }
+       }
+       kfree(connector_set);
+       drm_mode_destroy(dev, mode);
+       drm_modeset_unlock_all(dev);
+       return ret;
+}
+
+int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+                              struct drm_property *property,
+                              uint64_t value)
+{
+       int ret = -EINVAL;
+       struct drm_crtc *crtc = obj_to_crtc(obj);
+
+       if (crtc->funcs->set_property)
+               ret = crtc->funcs->set_property(crtc, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
 
        return ret;
 }
@@ -2200,37 +1047,6 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
        return dev->driver->dumb_destroy(file_priv, dev, args->handle);
 }
 
-/**
- * drm_rotation_simplify() - Try to simplify the rotation
- * @rotation: Rotation to be simplified
- * @supported_rotations: Supported rotations
- *
- * Attempt to simplify the rotation to a form that is supported.
- * Eg. if the hardware supports everything except DRM_REFLECT_X
- * one could call this function like this:
- *
- * drm_rotation_simplify(rotation, DRM_ROTATE_0 |
- *                       DRM_ROTATE_90 | DRM_ROTATE_180 |
- *                       DRM_ROTATE_270 | DRM_REFLECT_Y);
- *
- * to eliminate the DRM_ROTATE_X flag. Depending on what kind of
- * transforms the hardware supports, this function may not
- * be able to produce a supported transform, so the caller should
- * check the result afterwards.
- */
-unsigned int drm_rotation_simplify(unsigned int rotation,
-                                  unsigned int supported_rotations)
-{
-       if (rotation & ~supported_rotations) {
-               rotation ^= DRM_REFLECT_X | DRM_REFLECT_Y;
-               rotation = (rotation & DRM_REFLECT_MASK) |
-                          BIT((ffs(rotation & DRM_ROTATE_MASK) + 1) % 4);
-       }
-
-       return rotation;
-}
-EXPORT_SYMBOL(drm_rotation_simplify);
-
 /**
  * drm_mode_config_init - initialize DRM mode_configuration structure
  * @dev: DRM device
@@ -2347,24 +1163,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_config_cleanup);
 
-struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
-                                                      unsigned int supported_rotations)
-{
-       static const struct drm_prop_enum_list props[] = {
-               { __builtin_ffs(DRM_ROTATE_0) - 1,   "rotate-0" },
-               { __builtin_ffs(DRM_ROTATE_90) - 1,  "rotate-90" },
-               { __builtin_ffs(DRM_ROTATE_180) - 1, "rotate-180" },
-               { __builtin_ffs(DRM_ROTATE_270) - 1, "rotate-270" },
-               { __builtin_ffs(DRM_REFLECT_X) - 1,  "reflect-x" },
-               { __builtin_ffs(DRM_REFLECT_Y) - 1,  "reflect-y" },
-       };
-
-       return drm_property_create_bitmask(dev, 0, "rotation",
-                                          props, ARRAY_SIZE(props),
-                                          supported_rotations);
-}
-EXPORT_SYMBOL(drm_mode_create_rotation_property);
-
 /**
  * DOC: Tile group
  *
@@ -2463,48 +1261,3 @@ struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
        return tg;
 }
 EXPORT_SYMBOL(drm_mode_create_tile_group);
-
-/**
- * drm_crtc_enable_color_mgmt - enable color management properties
- * @crtc: DRM CRTC
- * @degamma_lut_size: the size of the degamma lut (before CSC)
- * @has_ctm: whether to attach ctm_property for CSC matrix
- * @gamma_lut_size: the size of the gamma lut (after CSC)
- *
- * This function lets the driver enable the color correction
- * properties on a CRTC. This includes 3 degamma, csc and gamma
- * properties that userspace can set and 2 size properties to inform
- * the userspace of the lut sizes. Each of the properties are
- * optional. The gamma and degamma properties are only attached if
- * their size is not 0 and ctm_property is only attached if has_ctm is
- * true.
- */
-void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
-                               uint degamma_lut_size,
-                               bool has_ctm,
-                               uint gamma_lut_size)
-{
-       struct drm_device *dev = crtc->dev;
-       struct drm_mode_config *config = &dev->mode_config;
-
-       if (degamma_lut_size) {
-               drm_object_attach_property(&crtc->base,
-                                          config->degamma_lut_property, 0);
-               drm_object_attach_property(&crtc->base,
-                                          config->degamma_lut_size_property,
-                                          degamma_lut_size);
-       }
-
-       if (has_ctm)
-               drm_object_attach_property(&crtc->base,
-                                          config->ctm_property, 0);
-
-       if (gamma_lut_size) {
-               drm_object_attach_property(&crtc->base,
-                                          config->gamma_lut_property, 0);
-               drm_object_attach_property(&crtc->base,
-                                          config->gamma_lut_size_property,
-                                          gamma_lut_size);
-       }
-}
-EXPORT_SYMBOL(drm_crtc_enable_color_mgmt);
index 4e6b57ae7188e34b86e7dc08d168249308b57b34..28295e5d0d9eaa0c5eddba195cc1c4b3d16fab0f 100644 (file)
 #include <drm/drm_dp_helper.h>
 
 /* drm_fb_helper.c */
+#ifdef CONFIG_DRM_FBDEV_EMULATION
 int drm_fb_helper_modinit(void);
+#else
+static inline int drm_fb_helper_modinit(void)
+{
+       return 0;
+}
+#endif
 
 /* drm_dp_aux_dev.c */
 #ifdef CONFIG_DRM_DP_AUX_CHARDEV
index 444e609078ccbcb9dad42960502c238fc8070edc..c48ba02c5365d6a49e8d0915d35b1d23cdd00c90 100644 (file)
@@ -36,8 +36,6 @@
 int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
                               struct drm_property *property,
                               uint64_t value);
-int drm_plane_check_pixel_format(const struct drm_plane *plane,
-                                u32 format);
 int drm_crtc_check_viewport(const struct drm_crtc *crtc,
                            int x, int y,
                            const struct drm_display_mode *mode,
@@ -56,28 +54,19 @@ int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
 /* IOCTLs */
 int drm_mode_getresources(struct drm_device *dev,
                          void *data, struct drm_file *file_priv);
-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_setcrtc(struct drm_device *dev,
                     void *data, struct drm_file *file_priv);
-int drm_mode_getplane(struct drm_device *dev,
-                     void *data, struct drm_file *file_priv);
-int drm_mode_setplane(struct drm_device *dev,
-                     void *data, struct drm_file *file_priv);
-int drm_mode_cursor_ioctl(struct drm_device *dev,
-                         void *data, struct drm_file *file_priv);
-int drm_mode_cursor2_ioctl(struct drm_device *dev,
-                          void *data, struct drm_file *file_priv);
+
+/* drm_color_mgmt.c */
+
+/* IOCTLs */
 int drm_mode_gamma_get_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv);
 int drm_mode_gamma_set_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv);
 
-int drm_mode_page_flip_ioctl(struct drm_device *dev,
-                            void *data, struct drm_file *file_priv);
-
 /* drm_property.c */
 void drm_property_destroy_user_blobs(struct drm_device *dev,
                                     struct drm_file *file_priv);
@@ -155,6 +144,9 @@ 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);
+int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
+                                    uint32_t src_w, uint32_t src_h,
+                                    const struct drm_framebuffer *fb);
 
 /* IOCTL */
 int drm_mode_addfb(struct drm_device *dev,
@@ -177,6 +169,23 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
 int drm_modeset_register_all(struct drm_device *dev);
 void drm_modeset_unregister_all(struct drm_device *dev);
 
-/* drm_blend.c */
-int drm_atomic_normalize_zpos(struct drm_device *dev,
-                             struct drm_atomic_state *state);
+
+/* drm_plane.c */
+int drm_plane_register_all(struct drm_device *dev);
+void drm_plane_unregister_all(struct drm_device *dev);
+int drm_plane_check_pixel_format(const struct drm_plane *plane,
+                                u32 format);
+
+/* IOCTL */
+int drm_mode_getplane_res(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv);
+int drm_mode_getplane(struct drm_device *dev,
+                     void *data, struct drm_file *file_priv);
+int drm_mode_setplane(struct drm_device *dev,
+                     void *data, struct drm_file *file_priv);
+int drm_mode_cursor_ioctl(struct drm_device *dev,
+                         void *data, struct drm_file *file_priv);
+int drm_mode_cursor2_ioctl(struct drm_device *dev,
+                          void *data, struct drm_file *file_priv);
+int drm_mode_page_flip_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv);
index 0ad20f1cdf693404d8392e393eeb65d099fa44c9..ac3924a877e0fe03bd58e9f75395074096802898 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/i2c.h>
+#include <linux/seq_file.h>
 #include <drm/drm_dp_helper.h>
 #include <drm/drmP.h>
 
index acf6a5f38920225d34a0046e0a58ca84cc7a1fe3..80c7f25b5b74a32df2e550db0277d0e5754f8523 100644 (file)
@@ -33,7 +33,6 @@
 #include <linux/mount.h>
 #include <linux/slab.h>
 #include <drm/drmP.h>
-#include <drm/drm_core.h>
 #include "drm_crtc_internal.h"
 #include "drm_legacy.h"
 #include "drm_internal.h"
@@ -46,8 +45,8 @@
 unsigned int drm_debug = 0;
 EXPORT_SYMBOL(drm_debug);
 
-MODULE_AUTHOR(CORE_AUTHOR);
-MODULE_DESCRIPTION(CORE_DESC);
+MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl");
+MODULE_DESCRIPTION("DRM shared core routines");
 MODULE_LICENSE("GPL and additional rights");
 MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug category.\n"
 "\t\tBit 0 (0x01) will enable CORE messages (drm core code)\n"
@@ -339,6 +338,9 @@ void drm_minor_release(struct drm_minor *minor)
 
 static int drm_dev_set_unique(struct drm_device *dev, const char *name)
 {
+       if (!name)
+               return -EINVAL;
+
        kfree(dev->unique);
        dev->unique = kstrdup(name, GFP_KERNEL);
 
@@ -589,7 +591,7 @@ EXPORT_SYMBOL(drm_dev_init);
  * own struct should look at using drm_dev_init() instead.
  *
  * RETURNS:
- * Pointer to new DRM device, or NULL if out of memory.
+ * Pointer to new DRM device, or ERR_PTR on failure.
  */
 struct drm_device *drm_dev_alloc(struct drm_driver *driver,
                                 struct device *parent)
@@ -599,12 +601,12 @@ struct drm_device *drm_dev_alloc(struct drm_driver *driver,
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
        if (!dev)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ret = drm_dev_init(dev, driver, parent);
        if (ret) {
                kfree(dev);
-               return NULL;
+               return ERR_PTR(ret);
        }
 
        return dev;
@@ -821,53 +823,48 @@ static const struct file_operations drm_stub_fops = {
        .llseek = noop_llseek,
 };
 
+static void drm_core_exit(void)
+{
+       unregister_chrdev(DRM_MAJOR, "drm");
+       debugfs_remove(drm_debugfs_root);
+       drm_sysfs_destroy();
+       idr_destroy(&drm_minors_idr);
+       drm_connector_ida_destroy();
+       drm_global_release();
+}
+
 static int __init drm_core_init(void)
 {
-       int ret = -ENOMEM;
+       int ret;
 
        drm_global_init();
        drm_connector_ida_init();
        idr_init(&drm_minors_idr);
 
-       if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
-               goto err_p1;
-
        ret = drm_sysfs_init();
        if (ret < 0) {
-               printk(KERN_ERR "DRM: Error creating drm class.\n");
-               goto err_p2;
+               DRM_ERROR("Cannot create DRM class: %d\n", ret);
+               goto error;
        }
 
        drm_debugfs_root = debugfs_create_dir("dri", NULL);
        if (!drm_debugfs_root) {
-               DRM_ERROR("Cannot create /sys/kernel/debug/dri\n");
-               ret = -1;
-               goto err_p3;
+               ret = -ENOMEM;
+               DRM_ERROR("Cannot create debugfs-root: %d\n", ret);
+               goto error;
        }
 
-       DRM_INFO("Initialized %s %d.%d.%d %s\n",
-                CORE_NAME, CORE_MAJOR, CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
+       ret = register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops);
+       if (ret < 0)
+               goto error;
+
+       DRM_INFO("Initialized\n");
        return 0;
-err_p3:
-       drm_sysfs_destroy();
-err_p2:
-       unregister_chrdev(DRM_MAJOR, "drm");
 
-       idr_destroy(&drm_minors_idr);
-err_p1:
+error:
+       drm_core_exit();
        return ret;
 }
 
-static void __exit drm_core_exit(void)
-{
-       debugfs_remove(drm_debugfs_root);
-       drm_sysfs_destroy();
-
-       unregister_chrdev(DRM_MAJOR, "drm");
-
-       drm_connector_ida_destroy();
-       idr_destroy(&drm_minors_idr);
-}
-
 module_init(drm_core_init);
 module_exit(drm_core_exit);
index 998a6743a586e1322530a737634629b7358c6d85..5c067719164d9a6c3ea93146fb47c8f7725bf198 100644 (file)
  *
  * Encoders represent the connecting element between the CRTC (as the overall
  * pixel pipeline, represented by struct &drm_crtc) and the connectors (as the
- * generic sink entity, represented by struct &drm_connector). Encoders are
- * objects exposed to userspace, originally to allow userspace to infer cloning
- * and connector/CRTC restrictions. Unfortunately almost all drivers get this
- * wrong, making the uabi pretty much useless. On top of that the exposed
- * restrictions are too simple for todays hardware, and the recommend way to
- * infer restrictions is by using the DRM_MODE_ATOMIC_TEST_ONLY flag for the
- * atomic IOCTL.
+ * generic sink entity, represented by struct &drm_connector). An encoder takes
+ * pixel data from a CRTC and converts it to a format suitable for any attached
+ * connector. Encoders are objects exposed to userspace, originally to allow
+ * userspace to infer cloning and connector/CRTC restrictions. Unfortunately
+ * almost all drivers get this wrong, making the uabi pretty much useless. On
+ * top of that the exposed restrictions are too simple for today's hardware, and
+ * the recommended way to infer restrictions is by using the
+ * DRM_MODE_ATOMIC_TEST_ONLY flag for the atomic IOCTL.
  *
  * Otherwise encoders aren't used in the uapi at all (any modeset request from
  * userspace directly connects a connector with a CRTC), drivers are therefore
  * free to use them however they wish. Modeset helper libraries make strong use
  * of encoders to facilitate code sharing. But for more complex settings it is
  * usually better to move shared code into a separate &drm_bridge. Compared to
- * encoders bridges also have the benefit of not being purely an internal
+ * encoders, bridges also have the benefit of being purely an internal
  * abstraction since they are not exposed to userspace at all.
  *
  * Encoders are initialized with drm_encoder_init() and cleaned up using
index c4d350086def84372c30aa44e7990d0e58be5e66..5e830281bebdba810580a307d9c3c50d7d216151 100644 (file)
@@ -41,6 +41,8 @@
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 
+#include "drm_crtc_helper_internal.h"
+
 static bool drm_fbdev_emulation = true;
 module_param_named(fbdev_emulation, drm_fbdev_emulation, bool, 0600);
 MODULE_PARM_DESC(fbdev_emulation,
index 036cd275c53e876635fe3716742f43e1b6475e65..e84faecf52251e49efdb8c53b2ccca345299dd8d 100644 (file)
@@ -199,7 +199,6 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
 
        filp->private_data = priv;
        priv->filp = filp;
-       priv->uid = current_euid();
        priv->pid = get_pid(task_pid(current));
        priv->minor = minor;
 
index 30dc01e6eb5da15245fa6d9b70e942c6c088de0e..398efd67cb937360647a544da9dd5afe78eaa6ff 100644 (file)
  * &drm_framebuffer.
  */
 
+int drm_framebuffer_check_src_coords(uint32_t src_x, uint32_t src_y,
+                                    uint32_t src_w, uint32_t src_h,
+                                    const struct drm_framebuffer *fb)
+{
+       unsigned int fb_width, fb_height;
+
+       fb_width = fb->width << 16;
+       fb_height = fb->height << 16;
+
+       /* Make sure source coordinates are inside the fb. */
+       if (src_w > fb_width ||
+           src_x > fb_width - src_w ||
+           src_h > fb_height ||
+           src_y > fb_height - src_h) {
+               DRM_DEBUG_KMS("Invalid source coordinates "
+                             "%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
+                             src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
+                             src_h >> 16, ((src_h & 0xffff) * 15625) >> 10,
+                             src_x >> 16, ((src_x & 0xffff) * 15625) >> 10,
+                             src_y >> 16, ((src_y & 0xffff) * 15625) >> 10);
+               return -ENOSPC;
+       }
+
+       return 0;
+}
+
 /**
  * drm_mode_addfb - add an FB to the graphics configuration
  * @dev: drm device for the ioctl
index 9134ae134667e2aaa0ebf36a7f0324d965de8af2..465bacd0a630455e72c3127e12a000cad80ca4db 100644 (file)
@@ -257,7 +257,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
 
        if (drm_core_check_feature(dev, DRIVER_PRIME))
                drm_gem_remove_prime_handles(obj, file_priv);
-       drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+       drm_vma_node_revoke(&obj->vma_node, file_priv);
 
        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
@@ -372,7 +372,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
 
        handle = ret;
 
-       ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
+       ret = drm_vma_node_allow(&obj->vma_node, file_priv);
        if (ret)
                goto err_remove;
 
@@ -386,7 +386,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
        return 0;
 
 err_revoke:
-       drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+       drm_vma_node_revoke(&obj->vma_node, file_priv);
 err_remove:
        spin_lock(&file_priv->table_lock);
        idr_remove(&file_priv->object_idr, handle);
@@ -991,7 +991,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
        if (!obj)
                return -EINVAL;
 
-       if (!drm_vma_node_is_allowed(node, filp)) {
+       if (!drm_vma_node_is_allowed(node, priv)) {
                drm_gem_object_unreference_unlocked(obj);
                return -EACCES;
        }
index 9ae353f4dd06a562cd226292e6e53b0b5517c5d5..1df2d33d0b40ed43e0cbd4623e014851b34ce581 100644 (file)
@@ -80,6 +80,7 @@ int drm_clients_info(struct seq_file *m, void *data)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        struct drm_file *priv;
+       kuid_t uid;
 
        seq_printf(m,
                   "%20s %5s %3s master a %5s %10s\n",
@@ -98,13 +99,14 @@ int drm_clients_info(struct seq_file *m, void *data)
 
                rcu_read_lock(); /* locks pid_task()->comm */
                task = pid_task(priv->pid, PIDTYPE_PID);
+               uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID;
                seq_printf(m, "%20s %5d %3d   %c    %c %5d %10u\n",
                           task ? task->comm : "<unknown>",
                           pid_vnr(priv->pid),
                           priv->minor->index,
                           drm_is_current_master(priv) ? 'y' : 'n',
                           priv->authenticated ? 'y' : 'n',
-                          from_kuid_munged(seq_user_ns(m), priv->uid),
+                          from_kuid_munged(seq_user_ns(m), uid),
                           priv->magic);
                rcu_read_unlock();
        }
index b86dc9b921a5e8bfc806d3f1e4a4107125335306..e66af289a016d0e1389201ee180d34a0dea200a5 100644 (file)
@@ -21,6 +21,9 @@
  * OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#define DRM_IF_MAJOR 1
+#define DRM_IF_MINOR 4
+
 /* drm_irq.c */
 extern unsigned int drm_timestamp_monotonic;
 
index 5f896e723f7395d2c39284c578507ac2f36e6fd1..867ab8c1582bf33f154c6519cd33f5c2f72a9be7 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/export.h>
 
 #include <drm/drmP.h>
-#include <drm/drm_core.h>
 
 #define DRM_IOCTL_VERSION32            DRM_IOWR(0x00, drm_version32_t)
 #define DRM_IOCTL_GET_UNIQUE32         DRM_IOWR(0x01, drm_unique32_t)
index b97c421c65f49e7f841fdfcba31c4498ee3067fd..0ad2c47f808fc1d732ef530eba96a6dd265a71c6 100644 (file)
@@ -29,7 +29,6 @@
  */
 
 #include <drm/drmP.h>
-#include <drm/drm_core.h>
 #include <drm/drm_auth.h>
 #include "drm_legacy.h"
 #include "drm_internal.h"
index d86362fc8ac6b3fe31afde5ca1c42ba7304625a7..3ceea9cb9d3e42a36f2811b2bea31d63445e4e42 100644 (file)
@@ -236,8 +236,8 @@ int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
        DRM_DEBUG("\n");
 
        dev = drm_dev_alloc(driver, &pdev->dev);
-       if (!dev)
-               return -ENOMEM;
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
 
        ret = pci_enable_device(pdev);
        if (ret)
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
new file mode 100644 (file)
index 0000000..cd0d475
--- /dev/null
@@ -0,0 +1,907 @@
+/*
+ * 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_plane.h>
+
+#include "drm_crtc_internal.h"
+
+/**
+ * DOC: overview
+ *
+ * A plane represents an image source that can be blended with or overlayed on
+ * top of a CRTC during the scanout process. Planes take their input data from a
+ * &drm_framebuffer object. The plane itself specifies the cropping and scaling
+ * of that image, and where it is placed on the visible are of a display
+ * pipeline, represented by &drm_crtc. A plane can also have additional
+ * properties that specify how the pixels are positioned and blended, like
+ * rotation or Z-position. All these properties are stored in &drm_plane_state.
+ *
+ * To create a plane, a KMS drivers allocates and zeroes an instances of
+ * struct &drm_plane (possibly as part of a larger structure) and registers it
+ * with a call to drm_universal_plane_init().
+ *
+ * Cursor and overlay planes are optional. All drivers should provide one
+ * primary plane per CRTC to avoid surprising userspace too much. See enum
+ * &drm_plane_type for a more in-depth discussion of these special uapi-relevant
+ * plane types. Special planes are associated with their CRTC by calling
+ * drm_crtc_init_with_planes().
+ *
+ * The type of a plane is exposed in the immutable "type" enumeration property,
+ * which has one of the following values: "Overlay", "Primary", "Cursor".
+ */
+
+static unsigned int drm_num_planes(struct drm_device *dev)
+{
+       unsigned int num = 0;
+       struct drm_plane *tmp;
+
+       drm_for_each_plane(tmp, dev) {
+               num++;
+       }
+
+       return num;
+}
+
+/**
+ * drm_universal_plane_init - Initialize a new universal plane object
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @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
+ *
+ * Initializes a plane object of type @type.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
+                            unsigned long possible_crtcs,
+                            const struct drm_plane_funcs *funcs,
+                            const uint32_t *formats, unsigned int format_count,
+                            enum drm_plane_type type,
+                            const char *name, ...)
+{
+       struct drm_mode_config *config = &dev->mode_config;
+       int ret;
+
+       ret = drm_mode_object_get(dev, &plane->base, DRM_MODE_OBJECT_PLANE);
+       if (ret)
+               return ret;
+
+       drm_modeset_lock_init(&plane->mutex);
+
+       plane->base.properties = &plane->properties;
+       plane->dev = dev;
+       plane->funcs = funcs;
+       plane->format_types = kmalloc_array(format_count, sizeof(uint32_t),
+                                           GFP_KERNEL);
+       if (!plane->format_types) {
+               DRM_DEBUG_KMS("out of memory when allocating plane\n");
+               drm_mode_object_unregister(dev, &plane->base);
+               return -ENOMEM;
+       }
+
+       if (name) {
+               va_list ap;
+
+               va_start(ap, name);
+               plane->name = kvasprintf(GFP_KERNEL, name, ap);
+               va_end(ap);
+       } else {
+               plane->name = kasprintf(GFP_KERNEL, "plane-%d",
+                                       drm_num_planes(dev));
+       }
+       if (!plane->name) {
+               kfree(plane->format_types);
+               drm_mode_object_unregister(dev, &plane->base);
+               return -ENOMEM;
+       }
+
+       memcpy(plane->format_types, formats, format_count * sizeof(uint32_t));
+       plane->format_count = format_count;
+       plane->possible_crtcs = possible_crtcs;
+       plane->type = type;
+
+       list_add_tail(&plane->head, &config->plane_list);
+       plane->index = config->num_total_plane++;
+       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+               config->num_overlay_plane++;
+
+       drm_object_attach_property(&plane->base,
+                                  config->plane_type_property,
+                                  plane->type);
+
+       if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
+               drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
+               drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
+               drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
+               drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
+               drm_object_attach_property(&plane->base, config->prop_crtc_w, 0);
+               drm_object_attach_property(&plane->base, config->prop_crtc_h, 0);
+               drm_object_attach_property(&plane->base, config->prop_src_x, 0);
+               drm_object_attach_property(&plane->base, config->prop_src_y, 0);
+               drm_object_attach_property(&plane->base, config->prop_src_w, 0);
+               drm_object_attach_property(&plane->base, config->prop_src_h, 0);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_universal_plane_init);
+
+int drm_plane_register_all(struct drm_device *dev)
+{
+       struct drm_plane *plane;
+       int ret = 0;
+
+       drm_for_each_plane(plane, dev) {
+               if (plane->funcs->late_register)
+                       ret = plane->funcs->late_register(plane);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+void drm_plane_unregister_all(struct drm_device *dev)
+{
+       struct drm_plane *plane;
+
+       drm_for_each_plane(plane, dev) {
+               if (plane->funcs->early_unregister)
+                       plane->funcs->early_unregister(plane);
+       }
+}
+
+/**
+ * drm_plane_init - Initialize a legacy plane
+ * @dev: DRM device
+ * @plane: plane object to init
+ * @possible_crtcs: bitmask of possible CRTCs
+ * @funcs: callbacks for the new plane
+ * @formats: array of supported formats (DRM_FORMAT\_\*)
+ * @format_count: number of elements in @formats
+ * @is_primary: plane type (primary vs overlay)
+ *
+ * Legacy API to initialize a DRM plane.
+ *
+ * New drivers should call drm_universal_plane_init() instead.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
+                  unsigned long possible_crtcs,
+                  const struct drm_plane_funcs *funcs,
+                  const uint32_t *formats, unsigned int format_count,
+                  bool is_primary)
+{
+       enum drm_plane_type type;
+
+       type = is_primary ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+       return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
+                                       formats, format_count, type, NULL);
+}
+EXPORT_SYMBOL(drm_plane_init);
+
+/**
+ * drm_plane_cleanup - Clean up the core plane usage
+ * @plane: plane to cleanup
+ *
+ * This function cleans up @plane and removes it from the DRM mode setting
+ * core. Note that the function does *not* free the plane structure itself,
+ * this is the responsibility of the caller.
+ */
+void drm_plane_cleanup(struct drm_plane *plane)
+{
+       struct drm_device *dev = plane->dev;
+
+       drm_modeset_lock_all(dev);
+       kfree(plane->format_types);
+       drm_mode_object_unregister(dev, &plane->base);
+
+       BUG_ON(list_empty(&plane->head));
+
+       /* Note that the plane_list is considered to be static; should we
+        * remove the drm_plane at runtime we would have to decrement all
+        * the indices on the drm_plane after us in the plane_list.
+        */
+
+       list_del(&plane->head);
+       dev->mode_config.num_total_plane--;
+       if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+               dev->mode_config.num_overlay_plane--;
+       drm_modeset_unlock_all(dev);
+
+       WARN_ON(plane->state && !plane->funcs->atomic_destroy_state);
+       if (plane->state && plane->funcs->atomic_destroy_state)
+               plane->funcs->atomic_destroy_state(plane, plane->state);
+
+       kfree(plane->name);
+
+       memset(plane, 0, sizeof(*plane));
+}
+EXPORT_SYMBOL(drm_plane_cleanup);
+
+/**
+ * drm_plane_from_index - find the registered plane at an index
+ * @dev: DRM device
+ * @idx: index of registered plane to find for
+ *
+ * Given a plane index, return the registered plane from DRM device's
+ * list of planes with matching index.
+ */
+struct drm_plane *
+drm_plane_from_index(struct drm_device *dev, int idx)
+{
+       struct drm_plane *plane;
+
+       drm_for_each_plane(plane, dev)
+               if (idx == plane->index)
+                       return plane;
+
+       return NULL;
+}
+EXPORT_SYMBOL(drm_plane_from_index);
+
+/**
+ * drm_plane_force_disable - Forcibly disable a plane
+ * @plane: plane to disable
+ *
+ * Forces the plane to be disabled.
+ *
+ * Used when the plane's current framebuffer is destroyed,
+ * and when restoring fbdev mode.
+ */
+void drm_plane_force_disable(struct drm_plane *plane)
+{
+       int ret;
+
+       if (!plane->fb)
+               return;
+
+       plane->old_fb = plane->fb;
+       ret = plane->funcs->disable_plane(plane);
+       if (ret) {
+               DRM_ERROR("failed to disable plane with busy fb\n");
+               plane->old_fb = NULL;
+               return;
+       }
+       /* disconnect the plane from the fb and crtc: */
+       drm_framebuffer_unreference(plane->old_fb);
+       plane->old_fb = NULL;
+       plane->fb = NULL;
+       plane->crtc = NULL;
+}
+EXPORT_SYMBOL(drm_plane_force_disable);
+
+/**
+ * drm_mode_plane_set_obj_prop - set the value of a property
+ * @plane: drm plane object to set property value for
+ * @property: property to set
+ * @value: value the property should be set to
+ *
+ * This functions sets a given property on a given plane object. This function
+ * calls the driver's ->set_property callback and changes the software state of
+ * the property if the callback succeeds.
+ *
+ * Returns:
+ * Zero on success, error code on failure.
+ */
+int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+                               struct drm_property *property,
+                               uint64_t value)
+{
+       int ret = -EINVAL;
+       struct drm_mode_object *obj = &plane->base;
+
+       if (plane->funcs->set_property)
+               ret = plane->funcs->set_property(plane, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
+
+       return ret;
+}
+EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
+
+int drm_mode_getplane_res(struct drm_device *dev, void *data,
+                         struct drm_file *file_priv)
+{
+       struct drm_mode_get_plane_res *plane_resp = data;
+       struct drm_mode_config *config;
+       struct drm_plane *plane;
+       uint32_t __user *plane_ptr;
+       int copied = 0;
+       unsigned num_planes;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       config = &dev->mode_config;
+
+       if (file_priv->universal_planes)
+               num_planes = config->num_total_plane;
+       else
+               num_planes = config->num_overlay_plane;
+
+       /*
+        * This ioctl is called twice, once to determine how much space is
+        * needed, and the 2nd time to fill it.
+        */
+       if (num_planes &&
+           (plane_resp->count_planes >= num_planes)) {
+               plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;
+
+               /* Plane lists are invariant, no locking needed. */
+               drm_for_each_plane(plane, dev) {
+                       /*
+                        * Unless userspace set the 'universal planes'
+                        * capability bit, only advertise overlays.
+                        */
+                       if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
+                           !file_priv->universal_planes)
+                               continue;
+
+                       if (put_user(plane->base.id, plane_ptr + copied))
+                               return -EFAULT;
+                       copied++;
+               }
+       }
+       plane_resp->count_planes = num_planes;
+
+       return 0;
+}
+
+int drm_mode_getplane(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
+{
+       struct drm_mode_get_plane *plane_resp = data;
+       struct drm_plane *plane;
+       uint32_t __user *format_ptr;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       plane = drm_plane_find(dev, plane_resp->plane_id);
+       if (!plane)
+               return -ENOENT;
+
+       drm_modeset_lock(&plane->mutex, NULL);
+       if (plane->crtc)
+               plane_resp->crtc_id = plane->crtc->base.id;
+       else
+               plane_resp->crtc_id = 0;
+
+       if (plane->fb)
+               plane_resp->fb_id = plane->fb->base.id;
+       else
+               plane_resp->fb_id = 0;
+       drm_modeset_unlock(&plane->mutex);
+
+       plane_resp->plane_id = plane->base.id;
+       plane_resp->possible_crtcs = plane->possible_crtcs;
+       plane_resp->gamma_size = 0;
+
+       /*
+        * This ioctl is called twice, once to determine how much space is
+        * needed, and the 2nd time to fill it.
+        */
+       if (plane->format_count &&
+           (plane_resp->count_format_types >= plane->format_count)) {
+               format_ptr = (uint32_t __user *)(unsigned long)plane_resp->format_type_ptr;
+               if (copy_to_user(format_ptr,
+                                plane->format_types,
+                                sizeof(uint32_t) * plane->format_count)) {
+                       return -EFAULT;
+               }
+       }
+       plane_resp->count_format_types = plane->format_count;
+
+       return 0;
+}
+
+int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
+{
+       unsigned int i;
+
+       for (i = 0; i < plane->format_count; i++) {
+               if (format == plane->format_types[i])
+                       return 0;
+       }
+
+       return -EINVAL;
+}
+
+/*
+ * setplane_internal - setplane handler for internal callers
+ *
+ * Note that we assume an extra reference has already been taken on fb.  If the
+ * update fails, this reference will be dropped before return; if it succeeds,
+ * the previous framebuffer (if any) will be unreferenced instead.
+ *
+ * src_{x,y,w,h} are provided in 16.16 fixed point format
+ */
+static int __setplane_internal(struct drm_plane *plane,
+                              struct drm_crtc *crtc,
+                              struct drm_framebuffer *fb,
+                              int32_t crtc_x, int32_t crtc_y,
+                              uint32_t crtc_w, uint32_t crtc_h,
+                              /* src_{x,y,w,h} values are 16.16 fixed point */
+                              uint32_t src_x, uint32_t src_y,
+                              uint32_t src_w, uint32_t src_h)
+{
+       int ret = 0;
+
+       /* No fb means shut it down */
+       if (!fb) {
+               plane->old_fb = plane->fb;
+               ret = plane->funcs->disable_plane(plane);
+               if (!ret) {
+                       plane->crtc = NULL;
+                       plane->fb = NULL;
+               } else {
+                       plane->old_fb = NULL;
+               }
+               goto out;
+       }
+
+       /* Check whether this plane is usable on this CRTC */
+       if (!(plane->possible_crtcs & drm_crtc_mask(crtc))) {
+               DRM_DEBUG_KMS("Invalid crtc for plane\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       /* Check whether this plane supports the fb pixel format. */
+       ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
+       if (ret) {
+               char *format_name = drm_get_format_name(fb->pixel_format);
+               DRM_DEBUG_KMS("Invalid pixel format %s\n", format_name);
+               kfree(format_name);
+               goto out;
+       }
+
+       /* Give drivers some help against integer overflows */
+       if (crtc_w > INT_MAX ||
+           crtc_x > INT_MAX - (int32_t) crtc_w ||
+           crtc_h > INT_MAX ||
+           crtc_y > INT_MAX - (int32_t) crtc_h) {
+               DRM_DEBUG_KMS("Invalid CRTC coordinates %ux%u+%d+%d\n",
+                             crtc_w, crtc_h, crtc_x, crtc_y);
+               ret = -ERANGE;
+               goto out;
+       }
+
+       ret = drm_framebuffer_check_src_coords(src_x, src_y, src_w, src_h, fb);
+       if (ret)
+               goto out;
+
+       plane->old_fb = plane->fb;
+       ret = plane->funcs->update_plane(plane, crtc, fb,
+                                        crtc_x, crtc_y, crtc_w, crtc_h,
+                                        src_x, src_y, src_w, src_h);
+       if (!ret) {
+               plane->crtc = crtc;
+               plane->fb = fb;
+               fb = NULL;
+       } else {
+               plane->old_fb = NULL;
+       }
+
+out:
+       if (fb)
+               drm_framebuffer_unreference(fb);
+       if (plane->old_fb)
+               drm_framebuffer_unreference(plane->old_fb);
+       plane->old_fb = NULL;
+
+       return ret;
+}
+
+static int setplane_internal(struct drm_plane *plane,
+                            struct drm_crtc *crtc,
+                            struct drm_framebuffer *fb,
+                            int32_t crtc_x, int32_t crtc_y,
+                            uint32_t crtc_w, uint32_t crtc_h,
+                            /* src_{x,y,w,h} values are 16.16 fixed point */
+                            uint32_t src_x, uint32_t src_y,
+                            uint32_t src_w, uint32_t src_h)
+{
+       int ret;
+
+       drm_modeset_lock_all(plane->dev);
+       ret = __setplane_internal(plane, crtc, fb,
+                                 crtc_x, crtc_y, crtc_w, crtc_h,
+                                 src_x, src_y, src_w, src_h);
+       drm_modeset_unlock_all(plane->dev);
+
+       return ret;
+}
+
+int drm_mode_setplane(struct drm_device *dev, void *data,
+                     struct drm_file *file_priv)
+{
+       struct drm_mode_set_plane *plane_req = data;
+       struct drm_plane *plane;
+       struct drm_crtc *crtc = NULL;
+       struct drm_framebuffer *fb = NULL;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       /*
+        * First, find the plane, crtc, and fb objects.  If not available,
+        * we don't bother to call the driver.
+        */
+       plane = drm_plane_find(dev, plane_req->plane_id);
+       if (!plane) {
+               DRM_DEBUG_KMS("Unknown plane ID %d\n",
+                             plane_req->plane_id);
+               return -ENOENT;
+       }
+
+       if (plane_req->fb_id) {
+               fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
+               if (!fb) {
+                       DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+                                     plane_req->fb_id);
+                       return -ENOENT;
+               }
+
+               crtc = drm_crtc_find(dev, plane_req->crtc_id);
+               if (!crtc) {
+                       DRM_DEBUG_KMS("Unknown crtc ID %d\n",
+                                     plane_req->crtc_id);
+                       return -ENOENT;
+               }
+       }
+
+       /*
+        * setplane_internal will take care of deref'ing either the old or new
+        * framebuffer depending on success.
+        */
+       return setplane_internal(plane, crtc, fb,
+                                plane_req->crtc_x, plane_req->crtc_y,
+                                plane_req->crtc_w, plane_req->crtc_h,
+                                plane_req->src_x, plane_req->src_y,
+                                plane_req->src_w, plane_req->src_h);
+}
+
+static int drm_mode_cursor_universal(struct drm_crtc *crtc,
+                                    struct drm_mode_cursor2 *req,
+                                    struct drm_file *file_priv)
+{
+       struct drm_device *dev = crtc->dev;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_mode_fb_cmd2 fbreq = {
+               .width = req->width,
+               .height = req->height,
+               .pixel_format = DRM_FORMAT_ARGB8888,
+               .pitches = { req->width * 4 },
+               .handles = { req->handle },
+       };
+       int32_t crtc_x, crtc_y;
+       uint32_t crtc_w = 0, crtc_h = 0;
+       uint32_t src_w = 0, src_h = 0;
+       int ret = 0;
+
+       BUG_ON(!crtc->cursor);
+       WARN_ON(crtc->cursor->crtc != crtc && crtc->cursor->crtc != NULL);
+
+       /*
+        * Obtain fb we'll be using (either new or existing) and take an extra
+        * reference to it if fb != null.  setplane will take care of dropping
+        * the reference if the plane update fails.
+        */
+       if (req->flags & DRM_MODE_CURSOR_BO) {
+               if (req->handle) {
+                       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);
+                       }
+                       fb->hot_x = req->hot_x;
+                       fb->hot_y = req->hot_y;
+               } else {
+                       fb = NULL;
+               }
+       } else {
+               fb = crtc->cursor->fb;
+               if (fb)
+                       drm_framebuffer_reference(fb);
+       }
+
+       if (req->flags & DRM_MODE_CURSOR_MOVE) {
+               crtc_x = req->x;
+               crtc_y = req->y;
+       } else {
+               crtc_x = crtc->cursor_x;
+               crtc_y = crtc->cursor_y;
+       }
+
+       if (fb) {
+               crtc_w = fb->width;
+               crtc_h = fb->height;
+               src_w = fb->width << 16;
+               src_h = fb->height << 16;
+       }
+
+       /*
+        * setplane_internal will take care of deref'ing either the old or new
+        * framebuffer depending on success.
+        */
+       ret = __setplane_internal(crtc->cursor, crtc, fb,
+                               crtc_x, crtc_y, crtc_w, crtc_h,
+                               0, 0, src_w, src_h);
+
+       /* Update successful; save new cursor position, if necessary */
+       if (ret == 0 && req->flags & DRM_MODE_CURSOR_MOVE) {
+               crtc->cursor_x = req->x;
+               crtc->cursor_y = req->y;
+       }
+
+       return ret;
+}
+
+static int drm_mode_cursor_common(struct drm_device *dev,
+                                 struct drm_mode_cursor2 *req,
+                                 struct drm_file *file_priv)
+{
+       struct drm_crtc *crtc;
+       int ret = 0;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
+               return -EINVAL;
+
+       crtc = drm_crtc_find(dev, req->crtc_id);
+       if (!crtc) {
+               DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
+               return -ENOENT;
+       }
+
+       /*
+        * If this crtc has a universal cursor plane, call that plane's update
+        * handler rather than using legacy cursor handlers.
+        */
+       drm_modeset_lock_crtc(crtc, crtc->cursor);
+       if (crtc->cursor) {
+               ret = drm_mode_cursor_universal(crtc, req, file_priv);
+               goto out;
+       }
+
+       if (req->flags & DRM_MODE_CURSOR_BO) {
+               if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
+                       ret = -ENXIO;
+                       goto out;
+               }
+               /* Turns off the cursor if handle is 0 */
+               if (crtc->funcs->cursor_set2)
+                       ret = crtc->funcs->cursor_set2(crtc, file_priv, req->handle,
+                                                     req->width, req->height, req->hot_x, req->hot_y);
+               else
+                       ret = crtc->funcs->cursor_set(crtc, file_priv, req->handle,
+                                                     req->width, req->height);
+       }
+
+       if (req->flags & DRM_MODE_CURSOR_MOVE) {
+               if (crtc->funcs->cursor_move) {
+                       ret = crtc->funcs->cursor_move(crtc, req->x, req->y);
+               } else {
+                       ret = -EFAULT;
+                       goto out;
+               }
+       }
+out:
+       drm_modeset_unlock_crtc(crtc);
+
+       return ret;
+
+}
+
+
+int drm_mode_cursor_ioctl(struct drm_device *dev,
+                         void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_cursor *req = data;
+       struct drm_mode_cursor2 new_req;
+
+       memcpy(&new_req, req, sizeof(struct drm_mode_cursor));
+       new_req.hot_x = new_req.hot_y = 0;
+
+       return drm_mode_cursor_common(dev, &new_req, file_priv);
+}
+
+/*
+ * Set the cursor configuration based on user request. This implements the 2nd
+ * version of the cursor ioctl, which allows userspace to additionally specify
+ * the hotspot of the pointer.
+ */
+int drm_mode_cursor2_ioctl(struct drm_device *dev,
+                          void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_cursor2 *req = data;
+
+       return drm_mode_cursor_common(dev, req, file_priv);
+}
+
+int drm_mode_page_flip_ioctl(struct drm_device *dev,
+                            void *data, struct drm_file *file_priv)
+{
+       struct drm_mode_crtc_page_flip_target *page_flip = data;
+       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb = NULL;
+       struct drm_pending_vblank_event *e = NULL;
+       u32 target_vblank = page_flip->sequence;
+       int ret = -EINVAL;
+
+       if (!drm_core_check_feature(dev, DRIVER_MODESET))
+               return -EINVAL;
+
+       if (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS)
+               return -EINVAL;
+
+       if (page_flip->sequence != 0 && !(page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET))
+               return -EINVAL;
+
+       /* Only one of the DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE/RELATIVE flags
+        * can be specified
+        */
+       if ((page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) == DRM_MODE_PAGE_FLIP_TARGET)
+               return -EINVAL;
+
+       if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
+               return -EINVAL;
+
+       crtc = drm_crtc_find(dev, page_flip->crtc_id);
+       if (!crtc)
+               return -ENOENT;
+
+       drm_modeset_lock_crtc(crtc, crtc->primary);
+       if (crtc->primary->fb == NULL) {
+               /* The framebuffer is currently unbound, presumably
+                * due to a hotplug event, that userspace has not
+                * yet discovered.
+                */
+               ret = -EBUSY;
+               goto out;
+       }
+
+       if (crtc->funcs->page_flip == NULL)
+               goto out;
+
+       fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
+       if (!fb) {
+               ret = -ENOENT;
+               goto out;
+       }
+
+       if (crtc->state) {
+               const struct drm_plane_state *state = crtc->primary->state;
+
+               ret = drm_framebuffer_check_src_coords(state->src_x,
+                                                      state->src_y,
+                                                      state->src_w,
+                                                      state->src_h,
+                                                      fb);
+       } else {
+               ret = drm_crtc_check_viewport(crtc, crtc->x, crtc->y, &crtc->mode, fb);
+       }
+       if (ret)
+               goto out;
+
+       if (crtc->primary->fb->pixel_format != fb->pixel_format) {
+               DRM_DEBUG_KMS("Page flip is not allowed to change frame buffer format.\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+               e = kzalloc(sizeof *e, GFP_KERNEL);
+               if (!e) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               e->event.base.type = DRM_EVENT_FLIP_COMPLETE;
+               e->event.base.length = sizeof(e->event);
+               e->event.user_data = page_flip->user_data;
+               ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base);
+               if (ret) {
+                       kfree(e);
+                       goto out;
+               }
+       }
+
+       crtc->primary->old_fb = crtc->primary->fb;
+       if (crtc->funcs->page_flip_target) {
+               u32 current_vblank;
+               int r;
+
+               r = drm_crtc_vblank_get(crtc);
+               if (r)
+                       return r;
+
+               current_vblank = drm_crtc_vblank_count(crtc);
+
+               switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
+               case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
+                       if ((int)(target_vblank - current_vblank) > 1) {
+                               DRM_DEBUG("Invalid absolute flip target %u, "
+                                         "must be <= %u\n", target_vblank,
+                                         current_vblank + 1);
+                               drm_crtc_vblank_put(crtc);
+                               return -EINVAL;
+                       }
+                       break;
+               case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
+                       if (target_vblank != 0 && target_vblank != 1) {
+                               DRM_DEBUG("Invalid relative flip target %u, "
+                                         "must be 0 or 1\n", target_vblank);
+                               drm_crtc_vblank_put(crtc);
+                               return -EINVAL;
+                       }
+                       target_vblank += current_vblank;
+                       break;
+               default:
+                       target_vblank = current_vblank +
+                               !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
+                       break;
+               }
+       } else if (crtc->funcs->page_flip == NULL ||
+                  (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
+               return -EINVAL;
+       }
+
+       if (crtc->funcs->page_flip_target)
+               ret = crtc->funcs->page_flip_target(crtc, fb, e,
+                                                   page_flip->flags,
+                                                   target_vblank);
+       else
+               ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
+       if (ret) {
+               if (page_flip->flags & DRM_MODE_PAGE_FLIP_EVENT)
+                       drm_event_cancel_free(dev, &e->base);
+               /* Keep the old fb, don't unref it. */
+               crtc->primary->old_fb = NULL;
+       } else {
+               crtc->primary->fb = fb;
+               /* Unref only the old framebuffer. */
+               fb = NULL;
+       }
+
+out:
+       if (ret && crtc->funcs->page_flip_target)
+               drm_crtc_vblank_put(crtc);
+       if (crtc->primary->old_fb)
+               drm_framebuffer_unreference(crtc->primary->old_fb);
+       crtc->primary->old_fb = NULL;
+       drm_modeset_unlock_crtc(crtc);
+
+       return ret;
+}
index 2c819ef90090dee3b8c154d5065fd77041e66f6b..026269851ce9f005e9eca687b2f9146e75bdf4f0 100644 (file)
@@ -48,8 +48,8 @@ static int drm_get_platform_dev(struct platform_device *platdev,
        DRM_DEBUG("\n");
 
        dev = drm_dev_alloc(driver, &platdev->dev);
-       if (!dev)
-               return -ENOMEM;
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
 
        dev->platformdev = platdev;
 
index 32dd821b7202a5492a5c7b184c775c329e7e2fb1..9a37196c1bf1728b7ddbc25f0e66937376cd09bc 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/export.h>
 
 #include <drm/drm_sysfs.h>
-#include <drm/drm_core.h>
 #include <drm/drmP.h>
 #include "drm_internal.h"
 
@@ -37,12 +36,7 @@ static char *drm_devnode(struct device *dev, umode_t *mode)
        return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
 }
 
-static CLASS_ATTR_STRING(version, S_IRUGO,
-               CORE_NAME " "
-               __stringify(CORE_MAJOR) "."
-               __stringify(CORE_MINOR) "."
-               __stringify(CORE_PATCHLEVEL) " "
-               CORE_DATE);
+static CLASS_ATTR_STRING(version, S_IRUGO, "drm 1.1.0 20060810");
 
 /**
  * drm_sysfs_init - initialize sysfs helpers
index 0aef432679f9a64a066d1c9dc77c06b37e088d4a..20cc33d1bfc1869201593ae78bda3b3f691fd232 100644 (file)
@@ -25,7 +25,6 @@
 #include <drm/drmP.h>
 #include <drm/drm_mm.h>
 #include <drm/drm_vma_manager.h>
-#include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/rbtree.h>
@@ -252,9 +251,9 @@ EXPORT_SYMBOL(drm_vma_offset_remove);
 /**
  * drm_vma_node_allow - Add open-file to list of allowed users
  * @node: Node to modify
- * @filp: Open file to add
+ * @tag: Tag of file to remove
  *
- * Add @filp to the list of allowed open-files for this node. If @filp is
+ * Add @tag to the list of allowed open-files for this node. If @tag is
  * already on this list, the ref-count is incremented.
  *
  * The list of allowed-users is preserved across drm_vma_offset_add() and
@@ -269,7 +268,7 @@ EXPORT_SYMBOL(drm_vma_offset_remove);
  * RETURNS:
  * 0 on success, negative error code on internal failure (out-of-mem)
  */
-int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp)
+int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
 {
        struct rb_node **iter;
        struct rb_node *parent = NULL;
@@ -290,10 +289,10 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp)
                parent = *iter;
                entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);
 
-               if (filp == entry->vm_filp) {
+               if (tag == entry->vm_tag) {
                        entry->vm_count++;
                        goto unlock;
-               } else if (filp > entry->vm_filp) {
+               } else if (tag > entry->vm_tag) {
                        iter = &(*iter)->rb_right;
                } else {
                        iter = &(*iter)->rb_left;
@@ -305,7 +304,7 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp)
                goto unlock;
        }
 
-       new->vm_filp = filp;
+       new->vm_tag = tag;
        new->vm_count = 1;
        rb_link_node(&new->vm_rb, parent, iter);
        rb_insert_color(&new->vm_rb, &node->vm_files);
@@ -321,17 +320,18 @@ EXPORT_SYMBOL(drm_vma_node_allow);
 /**
  * drm_vma_node_revoke - Remove open-file from list of allowed users
  * @node: Node to modify
- * @filp: Open file to remove
+ * @tag: Tag of file to remove
  *
- * Decrement the ref-count of @filp in the list of allowed open-files on @node.
- * If the ref-count drops to zero, remove @filp from the list. You must call
- * this once for every drm_vma_node_allow() on @filp.
+ * Decrement the ref-count of @tag in the list of allowed open-files on @node.
+ * If the ref-count drops to zero, remove @tag from the list. You must call
+ * this once for every drm_vma_node_allow() on @tag.
  *
  * This is locked against concurrent access internally.
  *
- * If @filp is not on the list, nothing is done.
+ * If @tag is not on the list, nothing is done.
  */
-void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct file *filp)
+void drm_vma_node_revoke(struct drm_vma_offset_node *node,
+                        struct drm_file *tag)
 {
        struct drm_vma_offset_file *entry;
        struct rb_node *iter;
@@ -341,13 +341,13 @@ void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct file *filp)
        iter = node->vm_files.rb_node;
        while (likely(iter)) {
                entry = rb_entry(iter, struct drm_vma_offset_file, vm_rb);
-               if (filp == entry->vm_filp) {
+               if (tag == entry->vm_tag) {
                        if (!--entry->vm_count) {
                                rb_erase(&entry->vm_rb, &node->vm_files);
                                kfree(entry);
                        }
                        break;
-               } else if (filp > entry->vm_filp) {
+               } else if (tag > entry->vm_tag) {
                        iter = iter->rb_right;
                } else {
                        iter = iter->rb_left;
@@ -361,9 +361,9 @@ EXPORT_SYMBOL(drm_vma_node_revoke);
 /**
  * drm_vma_node_is_allowed - Check whether an open-file is granted access
  * @node: Node to check
- * @filp: Open-file to check for
+ * @tag: Tag of file to remove
  *
- * Search the list in @node whether @filp is currently on the list of allowed
+ * Search the list in @node whether @tag is currently on the list of allowed
  * open-files (see drm_vma_node_allow()).
  *
  * This is locked against concurrent access internally.
@@ -372,7 +372,7 @@ EXPORT_SYMBOL(drm_vma_node_revoke);
  * true iff @filp is on the list
  */
 bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
-                            struct file *filp)
+                            struct drm_file *tag)
 {
        struct drm_vma_offset_file *entry;
        struct rb_node *iter;
@@ -382,9 +382,9 @@ bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
        iter = node->vm_files.rb_node;
        while (likely(iter)) {
                entry = rb_entry(iter, struct drm_vma_offset_file, vm_rb);
-               if (filp == entry->vm_filp)
+               if (tag == entry->vm_tag)
                        break;
-               else if (filp > entry->vm_filp)
+               else if (tag > entry->vm_tag)
                        iter = iter->rb_right;
                else
                        iter = iter->rb_left;
index e3164d90399dcfa83c8f4cc0181b87fe3002c361..aa687669e22b4b05cbbc98f4af5e72ef62979e81 100644 (file)
@@ -529,8 +529,8 @@ static int etnaviv_bind(struct device *dev)
        int ret;
 
        drm = drm_dev_alloc(&etnaviv_drm_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv) {
index 092aaecc7482470389446a881b19c97d8a4647ea..0884c45aefe84a9800b2ec95c57d0f44d1259835 100644 (file)
@@ -410,8 +410,8 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev)
        fsl_dev->tcon = fsl_tcon_init(dev);
 
        drm = drm_dev_alloc(driver, dev);
-       if (!drm) {
-               ret = -ENOMEM;
+       if (IS_ERR(drm)) {
+               ret = PTR_ERR(drm);
                goto disable_pix_clk;
        }
 
index 1fc2f502d20ddbb60aec4070c28ed3104978c86c..90377a609c986e836f3c90e03ed327b0af10ac27 100644 (file)
@@ -207,8 +207,8 @@ static int kirin_drm_bind(struct device *dev)
        int ret;
 
        drm_dev = drm_dev_alloc(driver, dev);
-       if (!drm_dev)
-               return -ENOMEM;
+       if (IS_ERR(drm_dev))
+               return PTR_ERR(drm_dev);
 
        drm_dev->platformdev = to_platform_device(dev);
 
index 72c1ae4e02d4315252a606a812fbe7a9a2017663..cf83f6507ec8211566f87cbf4878e5d76c3eff0b 100644 (file)
@@ -294,8 +294,8 @@ static int mtk_drm_bind(struct device *dev)
        int ret;
 
        drm = drm_dev_alloc(&mtk_drm_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        drm->dev_private = private;
        private->drm = drm;
index 68268e55d595c343eed84053cb5bc19b4918f529..919b35f2ad2487443c97dc3af28916d67ba6c0fb 100644 (file)
@@ -150,7 +150,8 @@ static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *f
 {
        struct mgag200_bo *mgabo = mgag200_bo(bo);
 
-       return drm_vma_node_verify_access(&mgabo->gem.vma_node, filp);
+       return drm_vma_node_verify_access(&mgabo->gem.vma_node,
+                                         filp->private_data);
 }
 
 static int mgag200_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
index 8a0237008f742a95d05c08c29139cfe81f535797..042bde48200d50b3b1866dcd9048355be91a7c51 100644 (file)
@@ -347,9 +347,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
        int ret;
 
        ddev = drm_dev_alloc(drv, dev);
-       if (!ddev) {
+       if (IS_ERR(ddev)) {
                dev_err(dev, "failed to allocate drm_device\n");
-               return -ENOMEM;
+               return PTR_ERR(ddev);
        }
 
        platform_set_drvdata(pdev, ddev);
index 8ab9ce5089fea60c8d94961d40a976d20ce338af..66f31c3eb8ba417ba6b972092c1e7553267587f6 100644 (file)
@@ -1315,7 +1315,8 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
        struct nouveau_bo *nvbo = nouveau_bo(bo);
 
-       return drm_vma_node_verify_access(&nvbo->gem.vma_node, filp);
+       return drm_vma_node_verify_access(&nvbo->gem.vma_node,
+                                         filp->private_data);
 }
 
 static int
index 652ab111dd74d899cc9aac867e05791e0a64229f..3100fd88a015f0e5288aade4c2c0e60027c2daed 100644 (file)
@@ -1067,8 +1067,8 @@ nouveau_platform_device_create(const struct nvkm_device_tegra_func *func,
                goto err_free;
 
        drm = drm_dev_alloc(&driver_platform, &pdev->dev);
-       if (!drm) {
-               err = -ENOMEM;
+       if (IS_ERR(drm)) {
+               err = PTR_ERR(drm);
                goto err_free;
        }
 
index a257ad26beefb95493399545e4715ecf447a01c6..e26c82db948b9f8ef9da2c14cd671c3b4782e1a4 100644 (file)
@@ -210,7 +210,8 @@ static int qxl_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 {
        struct qxl_bo *qbo = to_qxl_bo(bo);
 
-       return drm_vma_node_verify_access(&qbo->gem_base.vma_node, filp);
+       return drm_vma_node_verify_access(&qbo->gem_base.vma_node,
+                                         filp->private_data);
 }
 
 static int qxl_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
index 93414aca60d6164d43375b4cf8f181cc8ef9a1e4..27ee0ab0e1a75629c21ebe87761f490cdd3bbcea 100644 (file)
@@ -237,7 +237,8 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp)
 
        if (radeon_ttm_tt_has_userptr(bo->ttm))
                return -EPERM;
-       return drm_vma_node_verify_access(&rbo->gem_base.vma_node, filp);
+       return drm_vma_node_verify_access(&rbo->gem_base.vma_node,
+                                         filp->private_data);
 }
 
 static void radeon_move_null(struct ttm_buffer_object *bo,
index 899ef7a2a7b4eaff0748c41e7a8e03cee201a2ee..73c971e39b1c723f5e712dd85eb491a85ced2ac4 100644 (file)
@@ -316,8 +316,8 @@ static int rcar_du_probe(struct platform_device *pdev)
        rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
 
        ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
-       if (!ddev)
-               return -ENOMEM;
+       if (IS_ERR(ddev))
+               return PTR_ERR(ddev);
 
        rcdu->ddev = ddev;
        ddev->dev_private = rcdu;
index 76eaf1de52e41e7253df80c9b5aaa927f64acc83..446b5d7e85f705404e73e8262c8c9d21f505f827 100644 (file)
@@ -143,8 +143,8 @@ static int rockchip_drm_bind(struct device *dev)
        int ret;
 
        drm_dev = drm_dev_alloc(&rockchip_drm_driver, dev);
-       if (!drm_dev)
-               return -ENOMEM;
+       if (IS_ERR(drm_dev))
+               return PTR_ERR(drm_dev);
 
        dev_set_drvdata(dev, drm_dev);
 
index 7cd3804c6deef355ae097661fdc35c320e5ed3d4..49ed3c4b7ac5e77b59c2ff50779069cc412ca94c 100644 (file)
@@ -365,8 +365,8 @@ static int sti_bind(struct device *dev)
        int ret;
 
        ddev = drm_dev_alloc(&sti_driver, dev);
-       if (!ddev)
-               return -ENOMEM;
+       if (IS_ERR(ddev))
+               return PTR_ERR(ddev);
 
        ddev->platformdev = to_platform_device(dev);
 
index 9059e3ef9786ece17db4c780502649c4dc89ae4c..0da9862ad8ed928e23a6a1e089551967ad5273e8 100644 (file)
@@ -121,8 +121,8 @@ static int sun4i_drv_bind(struct device *dev)
        int ret;
 
        drm = drm_dev_alloc(&sun4i_drv_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
        if (!drv) {
index 4b9f1c79cd7b01f4ba70e52743f7592d1ce014dd..8ab47b502d8382f9740e6795e56bf0afd545b632 100644 (file)
@@ -983,8 +983,8 @@ static int host1x_drm_probe(struct host1x_device *dev)
        int err;
 
        drm = drm_dev_alloc(driver, &dev->dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
 
        dev_set_drvdata(&dev->dev, drm);
 
index 208768922030a7ff792fa958d772cb72f9ebb4cb..cb9df104fe5be3c15a4aa19c238c22d2efc49830 100644 (file)
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "drm_flip_work.h"
-#include <drm/drm_plane_helper.h>
+#include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_flip_work.h>
+#include <drm/drm_plane_helper.h>
 
 #include "tilcdc_drv.h"
 #include "tilcdc_regs.h"
index f0851db6ba6ca56ae4462b6e9922036959328883..cc45d98f9bb5fb749071b2f0bd0e15e16e6cf423 100644 (file)
@@ -86,8 +86,8 @@ static int udl_usb_probe(struct usb_interface *interface,
        int r;
 
        dev = drm_dev_alloc(&driver, &interface->dev);
-       if (!dev)
-               return -ENOMEM;
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
 
        r = drm_dev_register(dev, (unsigned long)udev);
        if (r)
index deec53545bea3edeba4385265788c662d55a1b59..3c9e7f64b9261efff0faef744f5131a4899cda16 100644 (file)
@@ -233,8 +233,8 @@ static int vc4_drm_bind(struct device *dev)
                return -ENOMEM;
 
        drm = drm_dev_alloc(&vc4_drm_driver, dev);
-       if (!drm)
-               return -ENOMEM;
+       if (IS_ERR(drm))
+               return PTR_ERR(drm);
        platform_set_drvdata(pdev, drm);
        vc4->dev = drm;
        drm->dev_private = vc4;
index c15bafb06665f0ec8c788cd1c21d7067dc5a8df3..f36c14729b5547b2a36f67b65255b73618063919 100644 (file)
@@ -334,8 +334,8 @@ static int __init vgem_init(void)
        int ret;
 
        vgem_device = drm_dev_alloc(&vgem_driver, NULL);
-       if (!vgem_device) {
-               ret = -ENOMEM;
+       if (IS_ERR(vgem_device)) {
+               ret = PTR_ERR(vgem_device);
                goto out;
        }
 
index a59d0e309bfc4cefaf71bb6b8604fe2cedf5a76f..26197dd95d5c95aa02e0af4ffd04b514cd4b6ab4 100644 (file)
@@ -54,8 +54,8 @@ int drm_virtio_init(struct drm_driver *driver, struct virtio_device *vdev)
        int ret;
 
        dev = drm_dev_alloc(driver, &vdev->dev);
-       if (!dev)
-               return -ENOMEM;
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
        dev->virtdev = vdev;
        vdev->priv = dev;
 
index e341e7f6eef5d564fd47dfd49ca5ea2fc1cd4c6d..c53dc90942e054e8722bea81f35e655957b638b6 100644 (file)
@@ -396,7 +396,6 @@ struct drm_file {
        unsigned is_master:1;
 
        struct pid *pid;
-       kuid_t uid;
        drm_magic_t magic;
        struct list_head lhead;
        struct drm_minor *minor;
index 856a9c85a8383b5c382c6537375a4e33f5e6e7c0..9701f2dfb7840fe3d67689482005449054360aac 100644 (file)
 
 #include <drm/drm_crtc.h>
 
+/**
+ * struct drm_crtc_commit - track modeset commits on a CRTC
+ *
+ * This structure is used to track pending modeset changes and atomic commit on
+ * a per-CRTC basis. Since updating the list should never block this structure
+ * is reference counted to allow waiters to safely wait on an event to complete,
+ * without holding any locks.
+ *
+ * It has 3 different events in total to allow a fine-grained synchronization
+ * between outstanding updates::
+ *
+ *     atomic commit thread                    hardware
+ *
+ *     write new state into hardware   ---->   ...
+ *     signal hw_done
+ *                                             switch to new state on next
+ *     ...                                     v/hblank
+ *
+ *     wait for buffers to show up             ...
+ *
+ *     ...                                     send completion irq
+ *                                             irq handler signals flip_done
+ *     cleanup old buffers
+ *
+ *     signal cleanup_done
+ *
+ *     wait for flip_done              <----
+ *     clean up atomic state
+ *
+ * The important bit to know is that cleanup_done is the terminal event, but the
+ * ordering between flip_done and hw_done is entirely up to the specific driver
+ * and modeset state change.
+ *
+ * For an implementation of how to use this look at
+ * drm_atomic_helper_setup_commit() from the atomic helper library.
+ */
+struct drm_crtc_commit {
+       /**
+        * @crtc:
+        *
+        * DRM CRTC for this commit.
+        */
+       struct drm_crtc *crtc;
+
+       /**
+        * @ref:
+        *
+        * Reference count for this structure. Needed to allow blocking on
+        * completions without the risk of the completion disappearing
+        * meanwhile.
+        */
+       struct kref ref;
+
+       /**
+        * @flip_done:
+        *
+        * Will be signaled when the hardware has flipped to the new set of
+        * buffers. Signals at the same time as when the drm event for this
+        * commit is sent to userspace, or when an out-fence is singalled. Note
+        * that for most hardware, in most cases this happens after @hw_done is
+        * signalled.
+        */
+       struct completion flip_done;
+
+       /**
+        * @hw_done:
+        *
+        * Will be signalled when all hw register changes for this commit have
+        * been written out. Especially when disabling a pipe this can be much
+        * later than than @flip_done, since that can signal already when the
+        * screen goes black, whereas to fully shut down a pipe more register
+        * I/O is required.
+        *
+        * Note that this does not need to include separately reference-counted
+        * resources like backing storage buffer pinning, or runtime pm
+        * management.
+        */
+       struct completion hw_done;
+
+       /**
+        * @cleanup_done:
+        *
+        * Will be signalled after old buffers have been cleaned up by calling
+        * drm_atomic_helper_cleanup_planes(). Since this can only happen after
+        * a vblank wait completed it might be a bit later. This completion is
+        * useful to throttle updates and avoid hardware updates getting ahead
+        * of the buffer cleanup too much.
+        */
+       struct completion cleanup_done;
+
+       /**
+        * @commit_entry:
+        *
+        * Entry on the per-CRTC commit_list. Protected by crtc->commit_lock.
+        */
+       struct list_head commit_entry;
+
+       /**
+        * @event:
+        *
+        * &drm_pending_vblank_event pointer to clean up private events.
+        */
+       struct drm_pending_vblank_event *event;
+};
+
+struct __drm_planes_state {
+       struct drm_plane *ptr;
+       struct drm_plane_state *state;
+};
+
+struct __drm_crtcs_state {
+       struct drm_crtc *ptr;
+       struct drm_crtc_state *state;
+       struct drm_crtc_commit *commit;
+};
+
+struct __drm_connnectors_state {
+       struct drm_connector *ptr;
+       struct drm_connector_state *state;
+};
+
+/**
+ * struct drm_atomic_state - the global state object for atomic updates
+ * @dev: parent DRM device
+ * @allow_modeset: allow full modeset
+ * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
+ * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL.
+ * @planes: pointer to array of structures with per-plane data
+ * @crtcs: pointer to array of CRTC pointers
+ * @num_connector: size of the @connectors and @connector_states arrays
+ * @connectors: pointer to array of structures with per-connector data
+ * @acquire_ctx: acquire context for this atomic modeset state update
+ */
+struct drm_atomic_state {
+       struct drm_device *dev;
+       bool allow_modeset : 1;
+       bool legacy_cursor_update : 1;
+       bool legacy_set_config : 1;
+       struct __drm_planes_state *planes;
+       struct __drm_crtcs_state *crtcs;
+       int num_connector;
+       struct __drm_connnectors_state *connectors;
+
+       struct drm_modeset_acquire_ctx *acquire_ctx;
+
+       /**
+        * @commit_work:
+        *
+        * Work item which can be used by the driver or helpers to execute the
+        * commit without blocking.
+        */
+       struct work_struct commit_work;
+};
+
 void drm_crtc_commit_put(struct drm_crtc_commit *commit);
 static inline void drm_crtc_commit_get(struct drm_crtc_commit *commit)
 {
diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h
new file mode 100644 (file)
index 0000000..36baa17
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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_BLEND_H__
+#define __DRM_BLEND_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+
+struct drm_device;
+struct drm_atomic_state;
+
+/*
+ * Rotation property bits. DRM_ROTATE_<degrees> rotates the image by the
+ * specified amount in degrees in counter clockwise direction. DRM_REFLECT_X and
+ * DRM_REFLECT_Y reflects the image along the specified axis prior to rotation
+ *
+ * WARNING: These defines are UABI since they're exposed in the rotation
+ * property.
+ */
+#define DRM_ROTATE_0   BIT(0)
+#define DRM_ROTATE_90  BIT(1)
+#define DRM_ROTATE_180 BIT(2)
+#define DRM_ROTATE_270 BIT(3)
+#define DRM_ROTATE_MASK (DRM_ROTATE_0   | DRM_ROTATE_90 | \
+                        DRM_ROTATE_180 | DRM_ROTATE_270)
+#define DRM_REFLECT_X  BIT(4)
+#define DRM_REFLECT_Y  BIT(5)
+#define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
+
+struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
+                                                      unsigned int supported_rotations);
+unsigned int drm_rotation_simplify(unsigned int rotation,
+                                  unsigned int supported_rotations);
+
+int drm_plane_create_zpos_property(struct drm_plane *plane,
+                                  unsigned int zpos,
+                                  unsigned int min, unsigned int max);
+int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
+                                            unsigned int zpos);
+int drm_atomic_normalize_zpos(struct drm_device *dev,
+                             struct drm_atomic_state *state);
+#endif
diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h
new file mode 100644 (file)
index 0000000..530a1d6
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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_BRIDGE_H__
+#define __DRM_BRIDGE_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_mode_object.h>
+#include <drm/drm_modes.h>
+
+struct drm_bridge;
+
+/**
+ * struct drm_bridge_funcs - drm_bridge control functions
+ */
+struct drm_bridge_funcs {
+       /**
+        * @attach:
+        *
+        * This callback is invoked whenever our bridge is being attached to a
+        * &drm_encoder.
+        *
+        * The attach callback is optional.
+        *
+        * RETURNS:
+        *
+        * Zero on success, error code on failure.
+        */
+       int (*attach)(struct drm_bridge *bridge);
+
+       /**
+        * @detach:
+        *
+        * This callback is invoked whenever our bridge is being detached from a
+        * &drm_encoder.
+        *
+        * The detach callback is optional.
+        */
+       void (*detach)(struct drm_bridge *bridge);
+
+       /**
+        * @mode_fixup:
+        *
+        * This callback is used to validate and adjust a mode. The paramater
+        * mode is the display mode that should be fed to the next element in
+        * the display chain, either the final &drm_connector or the next
+        * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
+        * requires. It can be modified by this callback and does not need to
+        * match mode.
+        *
+        * This is the only hook that allows a bridge to reject a modeset. If
+        * this function passes all other callbacks must succeed for this
+        * configuration.
+        *
+        * The mode_fixup callback is optional.
+        *
+        * NOTE:
+        *
+        * This function is called in the check 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.
+        *
+        * RETURNS:
+        *
+        * True if an acceptable configuration is possible, false if the modeset
+        * operation should be rejected.
+        */
+       bool (*mode_fixup)(struct drm_bridge *bridge,
+                          const struct drm_display_mode *mode,
+                          struct drm_display_mode *adjusted_mode);
+       /**
+        * @disable:
+        *
+        * This callback should disable the bridge. It is called right before
+        * the preceding element in the display pipe is disabled. If the
+        * preceding element is a bridge this means it's called before that
+        * bridge's ->disable() function. If the preceding element is a
+        * &drm_encoder it's called right before the encoder's ->disable(),
+        * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+        *
+        * The bridge can assume that the display pipe (i.e. clocks and timing
+        * signals) feeding it is still running when this callback is called.
+        *
+        * The disable callback is optional.
+        */
+       void (*disable)(struct drm_bridge *bridge);
+
+       /**
+        * @post_disable:
+        *
+        * This callback should disable the bridge. It is called right after
+        * the preceding element in the display pipe is disabled. If the
+        * preceding element is a bridge this means it's called after that
+        * bridge's ->post_disable() function. If the preceding element is a
+        * &drm_encoder it's called right after the encoder's ->disable(),
+        * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+        *
+        * The bridge must assume that the display pipe (i.e. clocks and timing
+        * singals) feeding it is no longer running when this callback is
+        * called.
+        *
+        * The post_disable callback is optional.
+        */
+       void (*post_disable)(struct drm_bridge *bridge);
+
+       /**
+        * @mode_set:
+        *
+        * This callback should set the given mode on the bridge. It is called
+        * after the ->mode_set() callback for the preceding element in the
+        * display pipeline has been called already. The display pipe (i.e.
+        * clocks and timing signals) is off when this function is called.
+        */
+       void (*mode_set)(struct drm_bridge *bridge,
+                        struct drm_display_mode *mode,
+                        struct drm_display_mode *adjusted_mode);
+       /**
+        * @pre_enable:
+        *
+        * This callback should enable the bridge. It is called right before
+        * the preceding element in the display pipe is enabled. If the
+        * preceding element is a bridge this means it's called before that
+        * bridge's ->pre_enable() function. If the preceding element is a
+        * &drm_encoder it's called right before the encoder's ->enable(),
+        * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+        *
+        * The display pipe (i.e. clocks and timing signals) feeding this bridge
+        * will not yet be running when this callback is called. The bridge must
+        * not enable the display link feeding the next bridge in the chain (if
+        * there is one) when this callback is called.
+        *
+        * The pre_enable callback is optional.
+        */
+       void (*pre_enable)(struct drm_bridge *bridge);
+
+       /**
+        * @enable:
+        *
+        * This callback should enable the bridge. It is called right after
+        * the preceding element in the display pipe is enabled. If the
+        * preceding element is a bridge this means it's called after that
+        * bridge's ->enable() function. If the preceding element is a
+        * &drm_encoder it's called right after the encoder's ->enable(),
+        * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
+        *
+        * The bridge can assume that the display pipe (i.e. clocks and timing
+        * signals) feeding it is running when this callback is called. This
+        * callback must enable the display link feeding the next bridge in the
+        * chain if there is one.
+        *
+        * The enable callback is optional.
+        */
+       void (*enable)(struct drm_bridge *bridge);
+};
+
+/**
+ * struct drm_bridge - central DRM bridge control structure
+ * @dev: DRM device this bridge belongs to
+ * @encoder: encoder to which this bridge is connected
+ * @next: the next bridge in the encoder chain
+ * @of_node: device node pointer to the bridge
+ * @list: to keep track of all added bridges
+ * @funcs: control functions
+ * @driver_private: pointer to the bridge driver's internal context
+ */
+struct drm_bridge {
+       struct drm_device *dev;
+       struct drm_encoder *encoder;
+       struct drm_bridge *next;
+#ifdef CONFIG_OF
+       struct device_node *of_node;
+#endif
+       struct list_head list;
+
+       const struct drm_bridge_funcs *funcs;
+       void *driver_private;
+};
+
+int drm_bridge_add(struct drm_bridge *bridge);
+void drm_bridge_remove(struct drm_bridge *bridge);
+struct drm_bridge *of_drm_find_bridge(struct device_node *np);
+int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
+void drm_bridge_detach(struct drm_bridge *bridge);
+
+bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
+                       const struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);
+void drm_bridge_disable(struct drm_bridge *bridge);
+void drm_bridge_post_disable(struct drm_bridge *bridge);
+void drm_bridge_mode_set(struct drm_bridge *bridge,
+                       struct drm_display_mode *mode,
+                       struct drm_display_mode *adjusted_mode);
+void drm_bridge_pre_enable(struct drm_bridge *bridge);
+void drm_bridge_enable(struct drm_bridge *bridge);
+
+#endif
diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h
new file mode 100644 (file)
index 0000000..c767238
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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_COLOR_MGMT_H__
+#define __DRM_COLOR_MGMT_H__
+
+#include <linux/ctype.h>
+
+void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
+                               uint degamma_lut_size,
+                               bool has_ctm,
+                               uint gamma_lut_size);
+
+int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
+                                int gamma_size);
+
+/**
+ * drm_color_lut_extract - clamp&round LUT entries
+ * @user_input: input value
+ * @bit_precision: number of bits the hw LUT supports
+ *
+ * Extract a degamma/gamma LUT value provided by user (in the form of
+ * &drm_color_lut entries) and round it to the precision supported by the
+ * hardware.
+ */
+static inline uint32_t drm_color_lut_extract(uint32_t user_input,
+                                            uint32_t bit_precision)
+{
+       uint32_t val = user_input;
+       uint32_t max = 0xffff >> (16 - bit_precision);
+
+       /* Round only if we're not using full precision. */
+       if (bit_precision < 16) {
+               val += 1UL << (16 - bit_precision - 1);
+               val >>= 16 - bit_precision;
+       }
+
+       return clamp_val(val, 0, max);
+}
+
+
+#endif
index 66b7d6744dd253a4a1aa1b552ea5f90b484f91cf..51a15deda161d94f628fd67438e0ccc6d28e3ca7 100644 (file)
 #include <linux/ctype.h>
 #include <drm/drm_mode_object.h>
 
+#include <uapi/drm/drm_mode.h>
+
+struct drm_device;
+
 struct drm_connector_helper_funcs;
 struct drm_device;
 struct drm_crtc;
@@ -181,14 +185,19 @@ int drm_display_info_set_bus_formats(struct drm_display_info *info,
 /**
  * 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() */
+       /**
+        * @crtc: CRTC to connect connector to, NULL if disabled.
+        *
+        * Do not change this directly, use drm_atomic_set_crtc_for_connector()
+        * instead.
+        */
+       struct drm_crtc *crtc;
 
        struct drm_encoder *best_encoder;
 
@@ -744,4 +753,19 @@ int drm_mode_connector_set_path_property(struct drm_connector *connector,
 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);
+
+/**
+ * drm_for_each_connector - iterate over all connectors
+ * @connector: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all connectors of @dev.
+ */
+#define drm_for_each_connector(connector, dev) \
+       for (assert_drm_connector_list_read_locked(&(dev)->mode_config),        \
+            connector = list_first_entry(&(dev)->mode_config.connector_list,   \
+                                         struct drm_connector, head);          \
+            &connector->head != (&(dev)->mode_config.connector_list);          \
+            connector = list_next_entry(connector, head))
+
 #endif
diff --git a/include/drm/drm_core.h b/include/drm/drm_core.h
deleted file mode 100644 (file)
index 4e75238..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2004 Jon Smirl <jonsmirl@gmail.com>
- *
- * 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, sub license,
- * 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS 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.
- */
-#define CORE_AUTHOR            "Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"
-
-#define CORE_NAME              "drm"
-#define CORE_DESC              "DRM shared core routines"
-#define CORE_DATE              "20060810"
-
-#define DRM_IF_MAJOR   1
-#define DRM_IF_MINOR   4
-
-#define CORE_MAJOR     1
-#define CORE_MINOR     1
-#define CORE_PATCHLEVEL 0
index 8ca71d66282b2f753e87ade53c3cf865313cc329..a544b750249373f5ac96bfe42167792493ff37b9 100644 (file)
 #include <drm/drm_connector.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_property.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_plane.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_color_mgmt.h>
 
 struct drm_device;
 struct drm_mode_set;
@@ -60,21 +65,6 @@ static inline uint64_t I642U64(int64_t val)
        return (uint64_t)*((uint64_t *)&val);
 }
 
-/*
- * Rotation property bits. DRM_ROTATE_<degrees> rotates the image by the
- * specified amount in degrees in counter clockwise direction. DRM_REFLECT_X and
- * DRM_REFLECT_Y reflects the image along the specified axis prior to rotation
- */
-#define DRM_ROTATE_0   BIT(0)
-#define DRM_ROTATE_90  BIT(1)
-#define DRM_ROTATE_180 BIT(2)
-#define DRM_ROTATE_270 BIT(3)
-#define DRM_ROTATE_MASK (DRM_ROTATE_0   | DRM_ROTATE_90 | \
-                        DRM_ROTATE_180 | DRM_ROTATE_270)
-#define DRM_REFLECT_X  BIT(4)
-#define DRM_REFLECT_Y  BIT(5)
-#define DRM_REFLECT_MASK (DRM_REFLECT_X | DRM_REFLECT_Y)
-
 /* data corresponds to displayid vend/prod/serial */
 struct drm_tile_group {
        struct kref refcount;
@@ -654,693 +644,6 @@ struct drm_crtc {
        struct drm_modeset_acquire_ctx *acquire_ctx;
 };
 
-/**
- * struct drm_plane_state - mutable plane state
- * @plane: backpointer to the plane
- * @crtc: currently bound CRTC, NULL if disabled
- * @fb: currently bound framebuffer
- * @fence: optional fence to wait for before scanning out @fb
- * @crtc_x: left position of visible portion of plane on crtc
- * @crtc_y: upper position of visible portion of plane on crtc
- * @crtc_w: width of visible portion of plane on crtc
- * @crtc_h: height of visible portion of plane on crtc
- * @src_x: left position of visible portion of plane within
- *     plane (in 16.16)
- * @src_y: upper position of visible portion of plane within
- *     plane (in 16.16)
- * @src_w: width of visible portion of plane (in 16.16)
- * @src_h: height of visible portion of plane (in 16.16)
- * @rotation: rotation of the plane
- * @zpos: priority of the given plane on crtc (optional)
- * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1
- *     where N is the number of active planes for given crtc
- * @src: clipped source coordinates of the plane (in 16.16)
- * @dst: clipped destination coordinates of the plane
- * @visible: visibility of the plane
- * @state: backpointer to global drm_atomic_state
- */
-struct drm_plane_state {
-       struct drm_plane *plane;
-
-       struct drm_crtc *crtc;   /* do not write directly, use drm_atomic_set_crtc_for_plane() */
-       struct drm_framebuffer *fb;  /* do not write directly, use drm_atomic_set_fb_for_plane() */
-       struct fence *fence;
-
-       /* Signed dest location allows it to be partially off screen */
-       int32_t crtc_x, crtc_y;
-       uint32_t crtc_w, crtc_h;
-
-       /* Source values are 16.16 fixed point */
-       uint32_t src_x, src_y;
-       uint32_t src_h, src_w;
-
-       /* Plane rotation */
-       unsigned int rotation;
-
-       /* Plane zpos */
-       unsigned int zpos;
-       unsigned int normalized_zpos;
-
-       /* Clipped coordinates */
-       struct drm_rect src, dst;
-
-       /*
-        * Is the plane actually visible? Can be false even
-        * if fb!=NULL and crtc!=NULL, due to clipping.
-        */
-       bool visible;
-
-       struct drm_atomic_state *state;
-};
-
-
-/**
- * struct drm_plane_funcs - driver plane control functions
- */
-struct drm_plane_funcs {
-       /**
-        * @update_plane:
-        *
-        * This is the legacy entry point to enable and configure the plane for
-        * the given CRTC and framebuffer. It is never called to disable the
-        * plane, i.e. the passed-in crtc and fb paramters are never NULL.
-        *
-        * The source rectangle in frame buffer memory coordinates is given by
-        * the src_x, src_y, src_w and src_h parameters (as 16.16 fixed point
-        * values). Devices that don't support subpixel plane coordinates can
-        * ignore the fractional part.
-        *
-        * The destination rectangle in CRTC coordinates is given by the
-        * crtc_x, crtc_y, crtc_w and crtc_h parameters (as integer values).
-        * Devices scale the source rectangle to the destination rectangle. If
-        * scaling is not supported, and the source rectangle size doesn't match
-        * the destination rectangle size, the driver must return a
-        * -<errorname>EINVAL</errorname> error.
-        *
-        * Drivers implementing atomic modeset should use
-        * drm_atomic_helper_update_plane() to implement this hook.
-        *
-        * RETURNS:
-        *
-        * 0 on success or a negative error code on failure.
-        */
-       int (*update_plane)(struct drm_plane *plane,
-                           struct drm_crtc *crtc, struct drm_framebuffer *fb,
-                           int crtc_x, int crtc_y,
-                           unsigned int crtc_w, unsigned int crtc_h,
-                           uint32_t src_x, uint32_t src_y,
-                           uint32_t src_w, uint32_t src_h);
-
-       /**
-        * @disable_plane:
-        *
-        * This is the legacy entry point to disable the plane. The DRM core
-        * calls this method in response to a DRM_IOCTL_MODE_SETPLANE IOCTL call
-        * with the frame buffer ID set to 0.  Disabled planes must not be
-        * processed by the CRTC.
-        *
-        * Drivers implementing atomic modeset should use
-        * drm_atomic_helper_disable_plane() to implement this hook.
-        *
-        * RETURNS:
-        *
-        * 0 on success or a negative error code on failure.
-        */
-       int (*disable_plane)(struct drm_plane *plane);
-
-       /**
-        * @destroy:
-        *
-        * Clean up plane resources. This is only called at driver unload time
-        * through drm_mode_config_cleanup() since a plane cannot be hotplugged
-        * in DRM.
-        */
-       void (*destroy)(struct drm_plane *plane);
-
-       /**
-        * @reset:
-        *
-        * Reset plane 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_plane_reset() to reset
-        * atomic state using this hook.
-        */
-       void (*reset)(struct drm_plane *plane);
-
-       /**
-        * @set_property:
-        *
-        * This is the legacy entry point to update a property attached to the
-        * plane.
-        *
-        * Drivers implementing atomic modeset should use
-        * drm_atomic_helper_plane_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_plane *plane,
-                           struct drm_property *property, uint64_t val);
-
-       /**
-        * @atomic_duplicate_state:
-        *
-        * Duplicate the current atomic state for this plane 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_plane_state should use
-        * drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
-        * state structure to extend it with driver-private state should use
-        * __drm_atomic_helper_plane_duplicate_state() to make sure shared state is
-        * duplicated in a consistent fashion across drivers.
-        *
-        * It is an error to call this hook before plane->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_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
-
-       /**
-        * @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_plane *plane,
-                                    struct drm_plane_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_plane_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 plane). 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_plane *plane,
-                                  struct drm_plane_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 GETPLANE IOCTL.
-        *
-        * Do not call this function directly, use
-        * drm_atomic_plane_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 should never happen, the core only asks for
-        * properties attached to this plane).
-        */
-       int (*atomic_get_property)(struct drm_plane *plane,
-                                  const struct drm_plane_state *state,
-                                  struct drm_property *property,
-                                  uint64_t *val);
-       /**
-        * @late_register:
-        *
-        * This optional hook can be used to register additional userspace
-        * interfaces attached to the plane like debugfs interfaces.
-        * It is called late in the driver load sequence from drm_dev_register().
-        * 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_plane *plane);
-
-       /**
-        * @early_unregister:
-        *
-        * This optional hook should be used to unregister the additional
-        * userspace interfaces attached to the plane from
-        * late_unregister(). It is called from drm_dev_unregister(),
-        * early in the driver unload sequence to disable userspace access
-        * before data structures are torndown.
-        */
-       void (*early_unregister)(struct drm_plane *plane);
-};
-
-enum drm_plane_type {
-       DRM_PLANE_TYPE_OVERLAY,
-       DRM_PLANE_TYPE_PRIMARY,
-       DRM_PLANE_TYPE_CURSOR,
-};
-
-
-/**
- * struct drm_plane - central DRM plane control structure
- * @dev: DRM device this plane belongs to
- * @head: for list management
- * @name: human readable name, can be overwritten by the driver
- * @base: base mode object
- * @possible_crtcs: pipes this plane can be bound to
- * @format_types: array of formats supported by this plane
- * @format_count: number of formats supported
- * @format_default: driver hasn't supplied supported formats for the plane
- * @crtc: currently bound CRTC
- * @fb: currently bound fb
- * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
- *     drm_mode_set_config_internal() to implement correct refcounting.
- * @funcs: helper functions
- * @properties: property tracking for this plane
- * @type: type of plane (overlay, primary, cursor)
- * @state: current atomic state for this plane
- * @zpos_property: zpos property for this plane
- * @helper_private: mid-layer private data
- */
-struct drm_plane {
-       struct drm_device *dev;
-       struct list_head head;
-
-       char *name;
-
-       /**
-        * @mutex:
-        *
-        * Protects modeset plane state, together with the mutex of &drm_crtc
-        * this plane is linked to (when active, getting actived or getting
-        * disabled).
-        */
-       struct drm_modeset_lock mutex;
-
-       struct drm_mode_object base;
-
-       uint32_t possible_crtcs;
-       uint32_t *format_types;
-       unsigned int format_count;
-       bool format_default;
-
-       struct drm_crtc *crtc;
-       struct drm_framebuffer *fb;
-
-       struct drm_framebuffer *old_fb;
-
-       const struct drm_plane_funcs *funcs;
-
-       struct drm_object_properties properties;
-
-       enum drm_plane_type type;
-
-       /**
-        * @index: Position inside the mode_config.list, can be used as an array
-        * index. It is invariant over the lifetime of the plane.
-        */
-       unsigned index;
-
-       const struct drm_plane_helper_funcs *helper_private;
-
-       struct drm_plane_state *state;
-
-       struct drm_property *zpos_property;
-};
-
-/**
- * struct drm_bridge_funcs - drm_bridge control functions
- */
-struct drm_bridge_funcs {
-       /**
-        * @attach:
-        *
-        * This callback is invoked whenever our bridge is being attached to a
-        * &drm_encoder.
-        *
-        * The attach callback is optional.
-        *
-        * RETURNS:
-        *
-        * Zero on success, error code on failure.
-        */
-       int (*attach)(struct drm_bridge *bridge);
-
-       /**
-        * @detach:
-        *
-        * This callback is invoked whenever our bridge is being detached from a
-        * &drm_encoder.
-        *
-        * The detach callback is optional.
-        */
-       void (*detach)(struct drm_bridge *bridge);
-
-       /**
-        * @mode_fixup:
-        *
-        * This callback is used to validate and adjust a mode. The paramater
-        * mode is the display mode that should be fed to the next element in
-        * the display chain, either the final &drm_connector or the next
-        * &drm_bridge. The parameter adjusted_mode is the input mode the bridge
-        * requires. It can be modified by this callback and does not need to
-        * match mode.
-        *
-        * This is the only hook that allows a bridge to reject a modeset. If
-        * this function passes all other callbacks must succeed for this
-        * configuration.
-        *
-        * The mode_fixup callback is optional.
-        *
-        * NOTE:
-        *
-        * This function is called in the check 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.
-        *
-        * RETURNS:
-        *
-        * True if an acceptable configuration is possible, false if the modeset
-        * operation should be rejected.
-        */
-       bool (*mode_fixup)(struct drm_bridge *bridge,
-                          const struct drm_display_mode *mode,
-                          struct drm_display_mode *adjusted_mode);
-       /**
-        * @disable:
-        *
-        * This callback should disable the bridge. It is called right before
-        * the preceding element in the display pipe is disabled. If the
-        * preceding element is a bridge this means it's called before that
-        * bridge's ->disable() function. If the preceding element is a
-        * &drm_encoder it's called right before the encoder's ->disable(),
-        * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
-        *
-        * The bridge can assume that the display pipe (i.e. clocks and timing
-        * signals) feeding it is still running when this callback is called.
-        *
-        * The disable callback is optional.
-        */
-       void (*disable)(struct drm_bridge *bridge);
-
-       /**
-        * @post_disable:
-        *
-        * This callback should disable the bridge. It is called right after
-        * the preceding element in the display pipe is disabled. If the
-        * preceding element is a bridge this means it's called after that
-        * bridge's ->post_disable() function. If the preceding element is a
-        * &drm_encoder it's called right after the encoder's ->disable(),
-        * ->prepare() or ->dpms() hook from struct &drm_encoder_helper_funcs.
-        *
-        * The bridge must assume that the display pipe (i.e. clocks and timing
-        * singals) feeding it is no longer running when this callback is
-        * called.
-        *
-        * The post_disable callback is optional.
-        */
-       void (*post_disable)(struct drm_bridge *bridge);
-
-       /**
-        * @mode_set:
-        *
-        * This callback should set the given mode on the bridge. It is called
-        * after the ->mode_set() callback for the preceding element in the
-        * display pipeline has been called already. The display pipe (i.e.
-        * clocks and timing signals) is off when this function is called.
-        */
-       void (*mode_set)(struct drm_bridge *bridge,
-                        struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode);
-       /**
-        * @pre_enable:
-        *
-        * This callback should enable the bridge. It is called right before
-        * the preceding element in the display pipe is enabled. If the
-        * preceding element is a bridge this means it's called before that
-        * bridge's ->pre_enable() function. If the preceding element is a
-        * &drm_encoder it's called right before the encoder's ->enable(),
-        * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
-        *
-        * The display pipe (i.e. clocks and timing signals) feeding this bridge
-        * will not yet be running when this callback is called. The bridge must
-        * not enable the display link feeding the next bridge in the chain (if
-        * there is one) when this callback is called.
-        *
-        * The pre_enable callback is optional.
-        */
-       void (*pre_enable)(struct drm_bridge *bridge);
-
-       /**
-        * @enable:
-        *
-        * This callback should enable the bridge. It is called right after
-        * the preceding element in the display pipe is enabled. If the
-        * preceding element is a bridge this means it's called after that
-        * bridge's ->enable() function. If the preceding element is a
-        * &drm_encoder it's called right after the encoder's ->enable(),
-        * ->commit() or ->dpms() hook from struct &drm_encoder_helper_funcs.
-        *
-        * The bridge can assume that the display pipe (i.e. clocks and timing
-        * signals) feeding it is running when this callback is called. This
-        * callback must enable the display link feeding the next bridge in the
-        * chain if there is one.
-        *
-        * The enable callback is optional.
-        */
-       void (*enable)(struct drm_bridge *bridge);
-};
-
-/**
- * struct drm_bridge - central DRM bridge control structure
- * @dev: DRM device this bridge belongs to
- * @encoder: encoder to which this bridge is connected
- * @next: the next bridge in the encoder chain
- * @of_node: device node pointer to the bridge
- * @list: to keep track of all added bridges
- * @funcs: control functions
- * @driver_private: pointer to the bridge driver's internal context
- */
-struct drm_bridge {
-       struct drm_device *dev;
-       struct drm_encoder *encoder;
-       struct drm_bridge *next;
-#ifdef CONFIG_OF
-       struct device_node *of_node;
-#endif
-       struct list_head list;
-
-       const struct drm_bridge_funcs *funcs;
-       void *driver_private;
-};
-
-/**
- * struct drm_crtc_commit - track modeset commits on a CRTC
- *
- * This structure is used to track pending modeset changes and atomic commit on
- * a per-CRTC basis. Since updating the list should never block this structure
- * is reference counted to allow waiters to safely wait on an event to complete,
- * without holding any locks.
- *
- * It has 3 different events in total to allow a fine-grained synchronization
- * between outstanding updates::
- *
- *     atomic commit thread                    hardware
- *
- *     write new state into hardware   ---->   ...
- *     signal hw_done
- *                                             switch to new state on next
- *     ...                                     v/hblank
- *
- *     wait for buffers to show up             ...
- *
- *     ...                                     send completion irq
- *                                             irq handler signals flip_done
- *     cleanup old buffers
- *
- *     signal cleanup_done
- *
- *     wait for flip_done              <----
- *     clean up atomic state
- *
- * The important bit to know is that cleanup_done is the terminal event, but the
- * ordering between flip_done and hw_done is entirely up to the specific driver
- * and modeset state change.
- *
- * For an implementation of how to use this look at
- * drm_atomic_helper_setup_commit() from the atomic helper library.
- */
-struct drm_crtc_commit {
-       /**
-        * @crtc:
-        *
-        * DRM CRTC for this commit.
-        */
-       struct drm_crtc *crtc;
-
-       /**
-        * @ref:
-        *
-        * Reference count for this structure. Needed to allow blocking on
-        * completions without the risk of the completion disappearing
-        * meanwhile.
-        */
-       struct kref ref;
-
-       /**
-        * @flip_done:
-        *
-        * Will be signaled when the hardware has flipped to the new set of
-        * buffers. Signals at the same time as when the drm event for this
-        * commit is sent to userspace, or when an out-fence is singalled. Note
-        * that for most hardware, in most cases this happens after @hw_done is
-        * signalled.
-        */
-       struct completion flip_done;
-
-       /**
-        * @hw_done:
-        *
-        * Will be signalled when all hw register changes for this commit have
-        * been written out. Especially when disabling a pipe this can be much
-        * later than than @flip_done, since that can signal already when the
-        * screen goes black, whereas to fully shut down a pipe more register
-        * I/O is required.
-        *
-        * Note that this does not need to include separately reference-counted
-        * resources like backing storage buffer pinning, or runtime pm
-        * management.
-        */
-       struct completion hw_done;
-
-       /**
-        * @cleanup_done:
-        *
-        * Will be signalled after old buffers have been cleaned up by calling
-        * drm_atomic_helper_cleanup_planes(). Since this can only happen after
-        * a vblank wait completed it might be a bit later. This completion is
-        * useful to throttle updates and avoid hardware updates getting ahead
-        * of the buffer cleanup too much.
-        */
-       struct completion cleanup_done;
-
-       /**
-        * @commit_entry:
-        *
-        * Entry on the per-CRTC commit_list. Protected by crtc->commit_lock.
-        */
-       struct list_head commit_entry;
-
-       /**
-        * @event:
-        *
-        * &drm_pending_vblank_event pointer to clean up private events.
-        */
-       struct drm_pending_vblank_event *event;
-};
-
-struct __drm_planes_state {
-       struct drm_plane *ptr;
-       struct drm_plane_state *state;
-};
-
-struct __drm_crtcs_state {
-       struct drm_crtc *ptr;
-       struct drm_crtc_state *state;
-       struct drm_crtc_commit *commit;
-};
-
-struct __drm_connnectors_state {
-       struct drm_connector *ptr;
-       struct drm_connector_state *state;
-};
-
-/**
- * struct drm_atomic_state - the global state object for atomic updates
- * @dev: parent DRM device
- * @allow_modeset: allow full modeset
- * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
- * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL.
- * @planes: pointer to array of structures with per-plane data
- * @crtcs: pointer to array of CRTC pointers
- * @num_connector: size of the @connectors and @connector_states arrays
- * @connectors: pointer to array of structures with per-connector data
- * @acquire_ctx: acquire context for this atomic modeset state update
- */
-struct drm_atomic_state {
-       struct drm_device *dev;
-       bool allow_modeset : 1;
-       bool legacy_cursor_update : 1;
-       bool legacy_set_config : 1;
-       struct __drm_planes_state *planes;
-       struct __drm_crtcs_state *crtcs;
-       int num_connector;
-       struct __drm_connnectors_state *connectors;
-
-       struct drm_modeset_acquire_ctx *acquire_ctx;
-
-       /**
-        * @commit_work:
-        *
-        * Work item which can be used by the driver or helpers to execute the
-        * commit without blocking.
-        */
-       struct work_struct commit_work;
-};
-
-
 /**
  * struct drm_mode_set - new values for a CRTC config change
  * @fb: framebuffer to use for new config
@@ -1991,35 +1294,7 @@ struct drm_mode_config {
        struct drm_mode_config_helper_funcs *helper_private;
 };
 
-/**
- * drm_for_each_plane_mask - iterate over planes specified by bitmask
- * @plane: the loop cursor
- * @dev: the DRM device
- * @plane_mask: bitmask of plane indices
- *
- * Iterate over all planes specified by bitmask.
- */
-#define drm_for_each_plane_mask(plane, dev, plane_mask) \
-       list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
-               for_each_if ((plane_mask) & (1 << drm_plane_index(plane)))
-
-/**
- * drm_for_each_encoder_mask - iterate over encoders specified by bitmask
- * @encoder: the loop cursor
- * @dev: the DRM device
- * @encoder_mask: bitmask of encoder indices
- *
- * Iterate over all encoders specified by bitmask.
- */
-#define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \
-       list_for_each_entry((encoder), &(dev)->mode_config.encoder_list, head) \
-               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_mode(x) container_of(x, struct drm_display_mode, base)
-#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
-#define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
-#define obj_to_plane(x) container_of(x, struct drm_plane, base)
 
 extern __printf(6, 7)
 int drm_crtc_init_with_planes(struct drm_device *dev,
@@ -2054,36 +1329,6 @@ static inline uint32_t drm_crtc_mask(struct drm_crtc *crtc)
        return 1 << drm_crtc_index(crtc);
 }
 
-extern __printf(8, 9)
-int drm_universal_plane_init(struct drm_device *dev,
-                            struct drm_plane *plane,
-                            unsigned long possible_crtcs,
-                            const struct drm_plane_funcs *funcs,
-                            const uint32_t *formats,
-                            unsigned int format_count,
-                            enum drm_plane_type type,
-                            const char *name, ...);
-extern int drm_plane_init(struct drm_device *dev,
-                         struct drm_plane *plane,
-                         unsigned long possible_crtcs,
-                         const struct drm_plane_funcs *funcs,
-                         const uint32_t *formats, unsigned int format_count,
-                         bool is_primary);
-extern void drm_plane_cleanup(struct drm_plane *plane);
-
-/**
- * drm_plane_index - find the index of a registered plane
- * @plane: plane to find index for
- *
- * Given a registered plane, return the index of that plane within a DRM
- * device's list of planes.
- */
-static inline unsigned int drm_plane_index(struct drm_plane *plane)
-{
-       return plane->index;
-}
-extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
-extern void drm_plane_force_disable(struct drm_plane *plane);
 extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
                                   int *hdisplay, int *vdisplay);
 extern int drm_crtc_force_disable(struct drm_crtc *crtc);
@@ -2093,9 +1338,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_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
-                                        int gamma_size);
-
 extern int drm_mode_set_config_internal(struct drm_mode_set *set);
 
 extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
@@ -2105,35 +1347,7 @@ extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
 extern void drm_mode_put_tile_group(struct drm_device *dev,
                                   struct drm_tile_group *tg);
 
-extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
-                                      struct drm_property *property,
-                                      uint64_t value);
-
-extern struct drm_property *drm_mode_create_rotation_property(struct drm_device *dev,
-                                                             unsigned int supported_rotations);
-extern unsigned int drm_rotation_simplify(unsigned int rotation,
-                                         unsigned int supported_rotations);
-extern void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
-                                      uint degamma_lut_size,
-                                      bool has_ctm,
-                                      uint gamma_lut_size);
-
-int drm_plane_create_zpos_property(struct drm_plane *plane,
-                                  unsigned int zpos,
-                                  unsigned int min, unsigned int max);
-
-int drm_plane_create_zpos_immutable_property(struct drm_plane *plane,
-                                            unsigned int zpos);
-
 /* Helpers */
-static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
-               uint32_t id)
-{
-       struct drm_mode_object *mo;
-       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE);
-       return mo ? obj_to_plane(mo) : NULL;
-}
-
 static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
        uint32_t id)
 {
@@ -2142,33 +1356,6 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
        return mo ? obj_to_crtc(mo) : NULL;
 }
 
-/*
- * Extract a degamma/gamma LUT value provided by user and round it to the
- * precision supported by the hardware.
- */
-static inline uint32_t drm_color_lut_extract(uint32_t user_input,
-                                            uint32_t bit_precision)
-{
-       uint32_t val = user_input;
-       uint32_t max = 0xffff >> (16 - bit_precision);
-
-       /* Round only if we're not using full precision. */
-       if (bit_precision < 16) {
-               val += 1UL << (16 - bit_precision - 1);
-               val >>= 16 - bit_precision;
-       }
-
-       return clamp_val(val, 0, max);
-}
-
-/* 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) \
-               for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
-
-#define drm_for_each_plane(plane, dev) \
-       list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
-
 #define drm_for_each_crtc(crtc, dev) \
        list_for_each_entry(crtc, &(dev)->mode_config.crtc_list, head)
 
@@ -2186,68 +1373,4 @@ assert_drm_connector_list_read_locked(struct drm_mode_config *mode_config)
                !drm_modeset_is_locked(&mode_config->connection_mutex));
 }
 
-#define drm_for_each_connector(connector, dev) \
-       for (assert_drm_connector_list_read_locked(&(dev)->mode_config),        \
-            connector = list_first_entry(&(dev)->mode_config.connector_list,   \
-                                         struct drm_connector, head);          \
-            &connector->head != (&(dev)->mode_config.connector_list);          \
-            connector = list_next_entry(connector, head))
-
-#define drm_for_each_encoder(encoder, dev) \
-       list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head)
-
-#define drm_for_each_fb(fb, dev) \
-       for (WARN_ON(!mutex_is_locked(&(dev)->mode_config.fb_lock)),            \
-            fb = list_first_entry(&(dev)->mode_config.fb_list, \
-                                         struct drm_framebuffer, head);        \
-            &fb->head != (&(dev)->mode_config.fb_list);                        \
-            fb = list_next_entry(fb, head))
-
-/* drm_edid.c */
-bool drm_probe_ddc(struct i2c_adapter *adapter);
-struct edid *drm_get_edid(struct drm_connector *connector,
-                         struct i2c_adapter *adapter);
-struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
-                                    struct i2c_adapter *adapter);
-struct edid *drm_edid_duplicate(const struct edid *edid);
-int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
-
-u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
-enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
-bool drm_detect_hdmi_monitor(struct edid *edid);
-bool drm_detect_monitor_audio(struct edid *edid);
-bool drm_rgb_quant_range_selectable(struct edid *edid);
-int drm_add_modes_noedid(struct drm_connector *connector,
-                        int hdisplay, int vdisplay);
-void drm_set_preferred_mode(struct drm_connector *connector,
-                           int hpref, int vpref);
-
-int drm_edid_header_is_valid(const u8 *raw_edid);
-bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
-                         bool *edid_corrupt);
-bool drm_edid_is_valid(struct edid *edid);
-void drm_edid_get_monitor_name(struct edid *edid, char *name,
-                              int buflen);
-struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
-                                          int hsize, int vsize, int fresh,
-                                          bool rb);
-
-/* drm_bridge.c */
-extern int drm_bridge_add(struct drm_bridge *bridge);
-extern void drm_bridge_remove(struct drm_bridge *bridge);
-extern struct drm_bridge *of_drm_find_bridge(struct device_node *np);
-extern int drm_bridge_attach(struct drm_device *dev, struct drm_bridge *bridge);
-extern void drm_bridge_detach(struct drm_bridge *bridge);
-
-bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
-                       const struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
-void drm_bridge_disable(struct drm_bridge *bridge);
-void drm_bridge_post_disable(struct drm_bridge *bridge);
-void drm_bridge_mode_set(struct drm_bridge *bridge,
-                       struct drm_display_mode *mode,
-                       struct drm_display_mode *adjusted_mode);
-void drm_bridge_pre_enable(struct drm_bridge *bridge);
-void drm_bridge_enable(struct drm_bridge *bridge);
-
 #endif /* __DRM_CRTC_H__ */
index 919933d1beb42241e233e9332a99911eeaa4c9cd..c3a7d440bc11f623735f43514f6d28d6fb21bafe 100644 (file)
@@ -25,6 +25,9 @@
 
 #include <linux/types.h>
 
+struct drm_device;
+struct i2c_adapter;
+
 #define EDID_LENGTH 128
 #define DDC_ADDR 0x50
 #define DDC_ADDR2 0x52 /* E-DDC 1.2 - where DisplayID can hide */
@@ -423,9 +426,36 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
        return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
 }
 
+bool drm_probe_ddc(struct i2c_adapter *adapter);
 struct edid *drm_do_get_edid(struct drm_connector *connector,
        int (*get_edid_block)(void *data, u8 *buf, unsigned int block,
                              size_t len),
        void *data);
+struct edid *drm_get_edid(struct drm_connector *connector,
+                         struct i2c_adapter *adapter);
+struct edid *drm_get_edid_switcheroo(struct drm_connector *connector,
+                                    struct i2c_adapter *adapter);
+struct edid *drm_edid_duplicate(const struct edid *edid);
+int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
+
+u8 drm_match_cea_mode(const struct drm_display_mode *to_match);
+enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code);
+bool drm_detect_hdmi_monitor(struct edid *edid);
+bool drm_detect_monitor_audio(struct edid *edid);
+bool drm_rgb_quant_range_selectable(struct edid *edid);
+int drm_add_modes_noedid(struct drm_connector *connector,
+                        int hdisplay, int vdisplay);
+void drm_set_preferred_mode(struct drm_connector *connector,
+                           int hpref, int vpref);
+
+int drm_edid_header_is_valid(const u8 *raw_edid);
+bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid,
+                         bool *edid_corrupt);
+bool drm_edid_is_valid(struct edid *edid);
+void drm_edid_get_monitor_name(struct edid *edid, char *name,
+                              int buflen);
+struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
+                                          int hsize, int vsize, int fresh,
+                                          bool rb);
 
 #endif /* __DRM_EDID_H__ */
index fce0203094f771c496d534103cad1f899bc834d2..387e33a4d6ee5bc7bea8551c6e8016858669588a 100644 (file)
@@ -224,4 +224,26 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
 
 void drm_encoder_cleanup(struct drm_encoder *encoder);
 
+/**
+ * drm_for_each_encoder_mask - iterate over encoders specified by bitmask
+ * @encoder: the loop cursor
+ * @dev: the DRM device
+ * @encoder_mask: bitmask of encoder indices
+ *
+ * Iterate over all encoders specified by bitmask.
+ */
+#define drm_for_each_encoder_mask(encoder, dev, encoder_mask) \
+       list_for_each_entry((encoder), &(dev)->mode_config.encoder_list, head) \
+               for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
+
+/**
+ * drm_for_each_encoder - iterate over all encoders
+ * @encoder: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all encoders of @dev.
+ */
+#define drm_for_each_encoder(encoder, dev) \
+       list_for_each_entry(encoder, &(dev)->mode_config.encoder_list, head)
+
 #endif
index 797fb5f80c45dcd572a0075431c03cb5e173905d..e19458dd1a43d53b0aad1f4b0db10890d2792db7 100644 (file)
@@ -287,11 +287,6 @@ int drm_fb_helper_add_one_connector(struct drm_fb_helper *fb_helper, struct drm_
 int drm_fb_helper_remove_one_connector(struct drm_fb_helper *fb_helper,
                                       struct drm_connector *connector);
 #else
-static inline int drm_fb_helper_modinit(void)
-{
-       return 0;
-}
-
 static inline void drm_fb_helper_prepare(struct drm_device *dev,
                                        struct drm_fb_helper *helper,
                                        const struct drm_fb_helper_funcs *funcs)
index b2554c50a903e488bd5497d11b2c5dfde2b53dbc..f5ae1f436a4bd8b9a66f5c3a45b750843dc5866b 100644 (file)
@@ -206,6 +206,8 @@ struct drm_framebuffer {
        struct list_head filp_head;
 };
 
+#define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
+
 int drm_framebuffer_init(struct drm_device *dev,
                         struct drm_framebuffer *fb,
                         const struct drm_framebuffer_funcs *funcs);
@@ -247,4 +249,19 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
 {
        return atomic_read(&fb->base.refcount.refcount);
 }
+
+/**
+ * drm_for_each_fb - iterate over all framebuffers
+ * @fb: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all framebuffers of @dev. User must hold the fb_lock from
+ * &drm_mode_config.
+ */
+#define drm_for_each_fb(fb, dev) \
+       for (WARN_ON(!mutex_is_locked(&(dev)->mode_config.fb_lock)),            \
+            fb = list_first_entry(&(dev)->mode_config.fb_list, \
+                                         struct drm_framebuffer, head);        \
+            &fb->head != (&(dev)->mode_config.fb_list);                        \
+            fb = list_next_entry(fb, head))
 #endif
index be3d93839ae2a145e56f4c436cbb7beb50b3565f..43460b21d112f3067aa85f56f650abb144eebfe9 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/kref.h>
 struct drm_object_properties;
 struct drm_property;
+struct drm_device;
 
 /**
  * struct drm_mode_object - base structure for modeset objects
index 011f199d3bcf0b0f8aa9f6dd7ac9f273dc82e49a..9934d91619c1823c80d277a50cc025873903b3a1 100644 (file)
 #ifndef __DRM_MODES_H__
 #define __DRM_MODES_H__
 
+#include <linux/hdmi.h>
+
 #include <drm/drm_mode_object.h>
 #include <drm/drm_connector.h>
 
+struct videomode;
+
 /*
  * 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,
@@ -403,6 +407,8 @@ struct drm_display_mode {
        enum hdmi_picture_aspect picture_aspect_ratio;
 };
 
+#define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
+
 /**
  * drm_mode_is_stereo - check for stereo mode flags
  * @mode: drm_display_mode to check
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
new file mode 100644 (file)
index 0000000..43cf193
--- /dev/null
@@ -0,0 +1,526 @@
+/*
+ * 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_PLANE_H__
+#define __DRM_PLANE_H__
+
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <drm/drm_mode_object.h>
+
+struct drm_crtc;
+
+/**
+ * struct drm_plane_state - mutable plane state
+ * @plane: backpointer to the plane
+ * @crtc: currently bound CRTC, NULL if disabled
+ * @fb: currently bound framebuffer
+ * @fence: optional fence to wait for before scanning out @fb
+ * @crtc_x: left position of visible portion of plane on crtc
+ * @crtc_y: upper position of visible portion of plane on crtc
+ * @crtc_w: width of visible portion of plane on crtc
+ * @crtc_h: height of visible portion of plane on crtc
+ * @src_x: left position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_y: upper position of visible portion of plane within
+ *     plane (in 16.16)
+ * @src_w: width of visible portion of plane (in 16.16)
+ * @src_h: height of visible portion of plane (in 16.16)
+ * @rotation: rotation of the plane
+ * @zpos: priority of the given plane on crtc (optional)
+ * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1
+ *     where N is the number of active planes for given crtc
+ * @src: clipped source coordinates of the plane (in 16.16)
+ * @dst: clipped destination coordinates of the plane
+ * @visible: visibility of the plane
+ * @state: backpointer to global drm_atomic_state
+ */
+struct drm_plane_state {
+       struct drm_plane *plane;
+
+       struct drm_crtc *crtc;   /* do not write directly, use drm_atomic_set_crtc_for_plane() */
+       struct drm_framebuffer *fb;  /* do not write directly, use drm_atomic_set_fb_for_plane() */
+       struct fence *fence;
+
+       /* Signed dest location allows it to be partially off screen */
+       int32_t crtc_x, crtc_y;
+       uint32_t crtc_w, crtc_h;
+
+       /* Source values are 16.16 fixed point */
+       uint32_t src_x, src_y;
+       uint32_t src_h, src_w;
+
+       /* Plane rotation */
+       unsigned int rotation;
+
+       /* Plane zpos */
+       unsigned int zpos;
+       unsigned int normalized_zpos;
+
+       /* Clipped coordinates */
+       struct drm_rect src, dst;
+
+       /*
+        * Is the plane actually visible? Can be false even
+        * if fb!=NULL and crtc!=NULL, due to clipping.
+        */
+       bool visible;
+
+       struct drm_atomic_state *state;
+};
+
+
+/**
+ * struct drm_plane_funcs - driver plane control functions
+ */
+struct drm_plane_funcs {
+       /**
+        * @update_plane:
+        *
+        * This is the legacy entry point to enable and configure the plane for
+        * the given CRTC and framebuffer. It is never called to disable the
+        * plane, i.e. the passed-in crtc and fb paramters are never NULL.
+        *
+        * The source rectangle in frame buffer memory coordinates is given by
+        * the src_x, src_y, src_w and src_h parameters (as 16.16 fixed point
+        * values). Devices that don't support subpixel plane coordinates can
+        * ignore the fractional part.
+        *
+        * The destination rectangle in CRTC coordinates is given by the
+        * crtc_x, crtc_y, crtc_w and crtc_h parameters (as integer values).
+        * Devices scale the source rectangle to the destination rectangle. If
+        * scaling is not supported, and the source rectangle size doesn't match
+        * the destination rectangle size, the driver must return a
+        * -<errorname>EINVAL</errorname> error.
+        *
+        * Drivers implementing atomic modeset should use
+        * drm_atomic_helper_update_plane() to implement this hook.
+        *
+        * RETURNS:
+        *
+        * 0 on success or a negative error code on failure.
+        */
+       int (*update_plane)(struct drm_plane *plane,
+                           struct drm_crtc *crtc, struct drm_framebuffer *fb,
+                           int crtc_x, int crtc_y,
+                           unsigned int crtc_w, unsigned int crtc_h,
+                           uint32_t src_x, uint32_t src_y,
+                           uint32_t src_w, uint32_t src_h);
+
+       /**
+        * @disable_plane:
+        *
+        * This is the legacy entry point to disable the plane. The DRM core
+        * calls this method in response to a DRM_IOCTL_MODE_SETPLANE IOCTL call
+        * with the frame buffer ID set to 0.  Disabled planes must not be
+        * processed by the CRTC.
+        *
+        * Drivers implementing atomic modeset should use
+        * drm_atomic_helper_disable_plane() to implement this hook.
+        *
+        * RETURNS:
+        *
+        * 0 on success or a negative error code on failure.
+        */
+       int (*disable_plane)(struct drm_plane *plane);
+
+       /**
+        * @destroy:
+        *
+        * Clean up plane resources. This is only called at driver unload time
+        * through drm_mode_config_cleanup() since a plane cannot be hotplugged
+        * in DRM.
+        */
+       void (*destroy)(struct drm_plane *plane);
+
+       /**
+        * @reset:
+        *
+        * Reset plane 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_plane_reset() to reset
+        * atomic state using this hook.
+        */
+       void (*reset)(struct drm_plane *plane);
+
+       /**
+        * @set_property:
+        *
+        * This is the legacy entry point to update a property attached to the
+        * plane.
+        *
+        * Drivers implementing atomic modeset should use
+        * drm_atomic_helper_plane_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_plane *plane,
+                           struct drm_property *property, uint64_t val);
+
+       /**
+        * @atomic_duplicate_state:
+        *
+        * Duplicate the current atomic state for this plane 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_plane_state should use
+        * drm_atomic_helper_plane_duplicate_state(). Drivers that subclass the
+        * state structure to extend it with driver-private state should use
+        * __drm_atomic_helper_plane_duplicate_state() to make sure shared state is
+        * duplicated in a consistent fashion across drivers.
+        *
+        * It is an error to call this hook before plane->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_plane_state *(*atomic_duplicate_state)(struct drm_plane *plane);
+
+       /**
+        * @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_plane *plane,
+                                    struct drm_plane_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_plane_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 plane). 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_plane *plane,
+                                  struct drm_plane_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 GETPLANE IOCTL.
+        *
+        * Do not call this function directly, use
+        * drm_atomic_plane_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 should never happen, the core only asks for
+        * properties attached to this plane).
+        */
+       int (*atomic_get_property)(struct drm_plane *plane,
+                                  const struct drm_plane_state *state,
+                                  struct drm_property *property,
+                                  uint64_t *val);
+       /**
+        * @late_register:
+        *
+        * This optional hook can be used to register additional userspace
+        * interfaces attached to the plane like debugfs interfaces.
+        * It is called late in the driver load sequence from drm_dev_register().
+        * 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_plane *plane);
+
+       /**
+        * @early_unregister:
+        *
+        * This optional hook should be used to unregister the additional
+        * userspace interfaces attached to the plane from
+        * late_unregister(). It is called from drm_dev_unregister(),
+        * early in the driver unload sequence to disable userspace access
+        * before data structures are torndown.
+        */
+       void (*early_unregister)(struct drm_plane *plane);
+};
+
+/**
+ * enum drm_plane_type - uapi plane type enumeration
+ *
+ * For historical reasons not all planes are made the same. This enumeration is
+ * used to tell the different types of planes apart to implement the different
+ * uapi semantics for them. For userspace which is universal plane aware and
+ * which is using that atomic IOCTL there's no difference between these planes
+ * (beyong what the driver and hardware can support of course).
+ *
+ * For compatibility with legacy userspace, only overlay planes are made
+ * available to userspace by default. Userspace clients may set the
+ * DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate that they
+ * wish to receive a universal plane list containing all plane types. See also
+ * drm_for_each_legacy_plane().
+ *
+ * WARNING: The values of this enum is UABI since they're exposed in the "type"
+ * property.
+ */
+enum drm_plane_type {
+       /**
+        * @DRM_PLANE_TYPE_OVERLAY:
+        *
+        * Overlay planes represent all non-primary, non-cursor planes. Some
+        * drivers refer to these types of planes as "sprites" internally.
+        */
+       DRM_PLANE_TYPE_OVERLAY,
+
+       /**
+        * @DRM_PLANE_TYPE_PRIMARY:
+        *
+        * Primary planes represent a "main" plane for a CRTC.  Primary planes
+        * are the planes operated upon by CRTC modesetting and flipping
+        * operations described in the page_flip and set_config hooks in struct
+        * &drm_crtc_funcs.
+        */
+       DRM_PLANE_TYPE_PRIMARY,
+
+       /**
+        * @DRM_PLANE_TYPE_CURSOR:
+        *
+        * Cursor planes represent a "cursor" plane for a CRTC.  Cursor planes
+        * are the planes operated upon by the DRM_IOCTL_MODE_CURSOR and
+        * DRM_IOCTL_MODE_CURSOR2 IOCTLs.
+        */
+       DRM_PLANE_TYPE_CURSOR,
+};
+
+
+/**
+ * struct drm_plane - central DRM plane control structure
+ * @dev: DRM device this plane belongs to
+ * @head: for list management
+ * @name: human readable name, can be overwritten by the driver
+ * @base: base mode object
+ * @possible_crtcs: pipes this plane can be bound to
+ * @format_types: array of formats supported by this plane
+ * @format_count: number of formats supported
+ * @format_default: driver hasn't supplied supported formats for the plane
+ * @crtc: currently bound CRTC
+ * @fb: currently bound fb
+ * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
+ *     drm_mode_set_config_internal() to implement correct refcounting.
+ * @funcs: helper functions
+ * @properties: property tracking for this plane
+ * @type: type of plane (overlay, primary, cursor)
+ * @state: current atomic state for this plane
+ * @zpos_property: zpos property for this plane
+ * @helper_private: mid-layer private data
+ */
+struct drm_plane {
+       struct drm_device *dev;
+       struct list_head head;
+
+       char *name;
+
+       /**
+        * @mutex:
+        *
+        * Protects modeset plane state, together with the mutex of &drm_crtc
+        * this plane is linked to (when active, getting actived or getting
+        * disabled).
+        */
+       struct drm_modeset_lock mutex;
+
+       struct drm_mode_object base;
+
+       uint32_t possible_crtcs;
+       uint32_t *format_types;
+       unsigned int format_count;
+       bool format_default;
+
+       struct drm_crtc *crtc;
+       struct drm_framebuffer *fb;
+
+       struct drm_framebuffer *old_fb;
+
+       const struct drm_plane_funcs *funcs;
+
+       struct drm_object_properties properties;
+
+       enum drm_plane_type type;
+
+       /**
+        * @index: Position inside the mode_config.list, can be used as an array
+        * index. It is invariant over the lifetime of the plane.
+        */
+       unsigned index;
+
+       const struct drm_plane_helper_funcs *helper_private;
+
+       struct drm_plane_state *state;
+
+       struct drm_property *zpos_property;
+};
+
+#define obj_to_plane(x) container_of(x, struct drm_plane, base)
+
+extern __printf(8, 9)
+int drm_universal_plane_init(struct drm_device *dev,
+                            struct drm_plane *plane,
+                            unsigned long possible_crtcs,
+                            const struct drm_plane_funcs *funcs,
+                            const uint32_t *formats,
+                            unsigned int format_count,
+                            enum drm_plane_type type,
+                            const char *name, ...);
+extern int drm_plane_init(struct drm_device *dev,
+                         struct drm_plane *plane,
+                         unsigned long possible_crtcs,
+                         const struct drm_plane_funcs *funcs,
+                         const uint32_t *formats, unsigned int format_count,
+                         bool is_primary);
+extern void drm_plane_cleanup(struct drm_plane *plane);
+
+/**
+ * drm_plane_index - find the index of a registered plane
+ * @plane: plane to find index for
+ *
+ * Given a registered plane, return the index of that plane within a DRM
+ * device's list of planes.
+ */
+static inline unsigned int drm_plane_index(struct drm_plane *plane)
+{
+       return plane->index;
+}
+extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
+extern void drm_plane_force_disable(struct drm_plane *plane);
+
+int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+                                      struct drm_property *property,
+                                      uint64_t value);
+
+/**
+ * drm_plane_find - find a &drm_plane
+ * @dev: DRM device
+ * @id: plane id
+ *
+ * Returns the plane with @id, NULL if it doesn't exist. Simple wrapper around
+ * drm_mode_object_find().
+ */
+static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
+               uint32_t id)
+{
+       struct drm_mode_object *mo;
+       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE);
+       return mo ? obj_to_plane(mo) : NULL;
+}
+
+/**
+ * drm_for_each_plane_mask - iterate over planes specified by bitmask
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ * @plane_mask: bitmask of plane indices
+ *
+ * Iterate over all planes specified by bitmask.
+ */
+#define drm_for_each_plane_mask(plane, dev, plane_mask) \
+       list_for_each_entry((plane), &(dev)->mode_config.plane_list, head) \
+               for_each_if ((plane_mask) & (1 << drm_plane_index(plane)))
+
+/**
+ * drm_for_each_legacy_plane - iterate over all planes for legacy userspace
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all legacy planes of @dev, excluding primary and cursor planes.
+ * This is useful for implementing userspace apis when userspace is not
+ * universal plane aware. See also enum &drm_plane_type.
+ */
+#define drm_for_each_legacy_plane(plane, dev) \
+       list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
+               for_each_if (plane->type == DRM_PLANE_TYPE_OVERLAY)
+
+/**
+ * drm_for_each_plane - iterate over all planes
+ * @plane: the loop cursor
+ * @dev: the DRM device
+ *
+ * Iterate over all planes of @dev, include primary and cursor planes.
+ */
+#define drm_for_each_plane(plane, dev) \
+       list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
+
+
+#endif
index 30ab289be05d1ffd2e53817d81f78d4f1a493d06..43c4b6a2046d6c8cc03636cdde0879193dd3899f 100644 (file)
@@ -219,6 +219,7 @@ struct drm_prop_enum_list {
 };
 
 #define obj_to_property(x) container_of(x, struct drm_property, base)
+#define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
 
 /**
  * drm_property_type_is - check the type of a property
index afba6fcac85314c36e2924bc40603ffe62941fc9..9c03895dc479dae56b84b8dd2f912bd499709eef 100644 (file)
  */
 
 #include <drm/drm_mm.h>
-#include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
+struct drm_file;
+
 struct drm_vma_offset_file {
        struct rb_node vm_rb;
-       struct file *vm_filp;
+       struct drm_file *vm_tag;
        unsigned long vm_count;
 };
 
@@ -60,10 +61,11 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
 void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
                           struct drm_vma_offset_node *node);
 
-int drm_vma_node_allow(struct drm_vma_offset_node *node, struct file *filp);
-void drm_vma_node_revoke(struct drm_vma_offset_node *node, struct file *filp);
+int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag);
+void drm_vma_node_revoke(struct drm_vma_offset_node *node,
+                        struct drm_file *tag);
 bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
-                            struct file *filp);
+                            struct drm_file *tag);
 
 /**
  * drm_vma_offset_exact_lookup_locked() - Look up node by exact address
@@ -214,9 +216,9 @@ static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,
 /**
  * drm_vma_node_verify_access() - Access verification helper for TTM
  * @node: Offset node
- * @filp: Open-file
+ * @tag: Tag of file to check
  *
- * This checks whether @filp is granted access to @node. It is the same as
+ * This checks whether @tag is granted access to @node. It is the same as
  * drm_vma_node_is_allowed() but suitable as drop-in helper for TTM
  * verify_access() callbacks.
  *
@@ -224,9 +226,9 @@ static inline void drm_vma_node_unmap(struct drm_vma_offset_node *node,
  * 0 if access is granted, -EACCES otherwise.
  */
 static inline int drm_vma_node_verify_access(struct drm_vma_offset_node *node,
-                                            struct file *filp)
+                                            struct drm_file *tag)
 {
-       return drm_vma_node_is_allowed(node, filp) ? 0 : -EACCES;
+       return drm_vma_node_is_allowed(node, tag) ? 0 : -EACCES;
 }
 
 #endif /* __DRM_VMA_MANAGER_H__ */
index 413303d37b56b554384cc59585db8fcf9654b639..5b287d6970b3a06677b8f55cfbd0bdc162c61181 100644 (file)
@@ -85,15 +85,12 @@ struct sync_file_info {
 #define SYNC_IOC_MERGE         _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data)
 
 /**
- * DOC: SYNC_IOC_FENCE_INFO - get detailed information on a fence
+ * DOC: SYNC_IOC_FILE_INFO - get detailed information on a sync_file
  *
- * Takes a struct sync_file_info_data with extra space allocated for pt_info.
- * Caller should write the size of the buffer into len.  On return, len is
- * updated to reflect the total size of the sync_file_info_data including
- * pt_info.
- *
- * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence.
- * To iterate over the sync_pt_infos, use the sync_pt_info.len field.
+ * Takes a struct sync_file_info. If num_fences is 0, the field is updated
+ * with the actual number of fences. If num_fences is > 0, the system will
+ * use the pointer provided on sync_fence_info to return up to num_fences of
+ * struct sync_fence_info, with detailed fence information.
  */
 #define SYNC_IOC_FILE_INFO     _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info)