Merge tag 'topic/drm-misc-2016-08-31' of git://anongit.freedesktop.org/drm-intel...
authorDave Airlie <airlied@redhat.com>
Wed, 31 Aug 2016 20:15:38 +0000 (06:15 +1000)
committerDave Airlie <airlied@redhat.com>
Wed, 31 Aug 2016 20:15:38 +0000 (06:15 +1000)
More -misc stuff
- moar drm_crtc.c split up&documentation
- some fixes for the simple kms helpers (Andrea)
- I included all the dri1 patches from David - we're not removing any code
  or drivers, and it seems to have worked as a wake-up call to motivate a
  few more people to upstream kms conversions for these. Feel free to
  revert if you disagree strongly.
- a few other single patches

* tag 'topic/drm-misc-2016-08-31' of git://anongit.freedesktop.org/drm-intel: (24 commits)
  drm: drm_probe_helper: Fix output_poll_work scheduling
  drm: bridge/dw-hdmi: Fix colorspace and scan information registers values
  drm/doc: Polish docs for drm_property&drm_property_blob
  drm: Unify handling of blob and object properties
  drm: Extract drm_property.[hc]
  drm: move drm_mode_legacy_fb_format to drm_fourcc.c
  drm/doc: Polish docs for drm_mode_object
  drm: Remove drm_mode_object->atomic_count
  drm: Extract drm_mode_object.[hc]
  drm/doc: Polish kerneldoc for encoders
  drm: Extract drm_encoder.[hc]
  drm/fb-helper: don't call remove_conflicting_framebuffers for FB=m && DRM=y
  drm/atomic-helper: Add NO_DISABLE_AFTER_MODESET flag support for plane commit
  drm/atomic-helper: Disable appropriate planes in disable_planes_on_crtc()
  drm/atomic-helper: Add atomic_disable CRTC helper callback
  drm: simple_kms_helper: add support for bridges
  drm: simple_kms_helper: make connector optional at init time
  drm/bridge: introduce bridge detaching mechanism
  drm/simple-helpers: Always add planes to the state update
  drm: reduce GETCLIENT to a minimum
  ...

1  2 
drivers/gpu/drm/Kconfig
drivers/gpu/drm/Makefile
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/rockchip/rockchip_drm_fb.c
include/drm/drm_crtc.h

diff --combined drivers/gpu/drm/Kconfig
index cbb64d9a82f8c7a6c4ef2644da76bdf556c28a33,c02be6a24c4791bab10fec2c9cb1fdbeae712b96..536b5d477c3b6d3e693bf65f0e4d35260aba5277
@@@ -108,24 -108,8 +108,8 @@@ config DRM_KMS_CMA_HELPE
  
  source "drivers/gpu/drm/i2c/Kconfig"
  
- config DRM_TDFX
-       tristate "3dfx Banshee/Voodoo3+"
-       depends on DRM && PCI
-       help
-         Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
-         graphics card.  If M is selected, the module will be called tdfx.
  source "drivers/gpu/drm/arm/Kconfig"
  
- config DRM_R128
-       tristate "ATI Rage 128"
-       depends on DRM && PCI
-       select FW_LOADER
-       help
-         Choose this option if you have an ATI Rage 128 graphics card.  If M
-         is selected, the module will be called r128.  AGP support for
-         this card is strongly suggested (unless you have a PCI version).
  config DRM_RADEON
        tristate "ATI Radeon"
        depends on DRM && PCI
@@@ -163,52 -147,14 +147,11 @@@ config DRM_AMDGP
          If M is selected, the module will be called amdgpu.
  
  source "drivers/gpu/drm/amd/amdgpu/Kconfig"
 -source "drivers/gpu/drm/amd/powerplay/Kconfig"
 -
 -source "drivers/gpu/drm/amd/acp/Kconfig"
  
  source "drivers/gpu/drm/nouveau/Kconfig"
  
- config DRM_I810
-       tristate "Intel I810"
-       # !PREEMPT because of missing ioctl locking
-       depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
-       help
-         Choose this option if you have an Intel I810 graphics card.  If M is
-         selected, the module will be called i810.  AGP support is required
-         for this driver to work.
  source "drivers/gpu/drm/i915/Kconfig"
  
- config DRM_MGA
-       tristate "Matrox g200/g400"
-       depends on DRM && PCI
-       select FW_LOADER
-       help
-         Choose this option if you have a Matrox G200, G400 or G450 graphics
-         card.  If M is selected, the module will be called mga.  AGP
-         support is required for this driver to work.
- config DRM_SIS
-       tristate "SiS video cards"
-       depends on DRM && AGP
-       depends on FB_SIS || FB_SIS=n
-       help
-         Choose this option if you have a SiS 630 or compatible video
-           chipset. If M is selected the module will be called sis. AGP
-           support is required for this driver to work.
- config DRM_VIA
-       tristate "Via unichrome video cards"
-       depends on DRM && PCI
-       help
-         Choose this option if you have a Via unichrome or compatible video
-         chipset. If M is selected the module will be called via.
- config DRM_SAVAGE
-       tristate "Savage video cards"
-       depends on DRM && PCI
-       help
-         Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
-         chipset. If M is selected the module will be called savage.
  config DRM_VGEM
        tristate "Virtual GEM provider"
        depends on DRM
@@@ -279,3 -225,82 +222,82 @@@ source "drivers/gpu/drm/arc/Kconfig
  source "drivers/gpu/drm/hisilicon/Kconfig"
  
  source "drivers/gpu/drm/mediatek/Kconfig"
+ # Keep legacy drivers last
+ menuconfig DRM_LEGACY
+       bool "Enable legacy drivers (DANGEROUS)"
+       depends on DRM
+       depends on BROKEN
+       help
+         Enable legacy DRI1 drivers. Those drivers expose unsafe and dangerous
+         APIs to user-space, which can be used to circumvent access
+         restrictions and other security measures. For backwards compatibility
+         those drivers are still available, but their use is highly
+         inadvisable and might harm your system.
+         You are recommended to use the safe modeset-only drivers instead, and
+         perform 3D emulation in user-space.
+         Unless you have strong reasons to go rogue, say "N".
+ if DRM_LEGACY
+ config DRM_TDFX
+       tristate "3dfx Banshee/Voodoo3+"
+       depends on DRM && PCI
+       help
+         Choose this option if you have a 3dfx Banshee or Voodoo3 (or later),
+         graphics card.  If M is selected, the module will be called tdfx.
+ config DRM_R128
+       tristate "ATI Rage 128"
+       depends on DRM && PCI
+       select FW_LOADER
+       help
+         Choose this option if you have an ATI Rage 128 graphics card.  If M
+         is selected, the module will be called r128.  AGP support for
+         this card is strongly suggested (unless you have a PCI version).
+ config DRM_I810
+       tristate "Intel I810"
+       # !PREEMPT because of missing ioctl locking
+       depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
+       help
+         Choose this option if you have an Intel I810 graphics card.  If M is
+         selected, the module will be called i810.  AGP support is required
+         for this driver to work.
+ config DRM_MGA
+       tristate "Matrox g200/g400"
+       depends on DRM && PCI
+       select FW_LOADER
+       help
+         Choose this option if you have a Matrox G200, G400 or G450 graphics
+         card.  If M is selected, the module will be called mga.  AGP
+         support is required for this driver to work.
+ config DRM_SIS
+       tristate "SiS video cards"
+       depends on DRM && AGP
+       depends on FB_SIS || FB_SIS=n
+       help
+         Choose this option if you have a SiS 630 or compatible video
+         chipset. If M is selected the module will be called sis. AGP
+         support is required for this driver to work.
+ config DRM_VIA
+       tristate "Via unichrome video cards"
+       depends on DRM && PCI
+       help
+         Choose this option if you have a Via unichrome or compatible video
+         chipset. If M is selected the module will be called via.
+ config DRM_SAVAGE
+       tristate "Savage video cards"
+       depends on DRM && PCI
+       help
+         Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
+         chipset. If M is selected the module will be called savage.
+ endif # DRM_LEGACY
diff --combined drivers/gpu/drm/Makefile
index 4054c94a230144ac8f0ed0678ac6427604d83c2a,12a966ec7298c15117bbe36847b1068a48d4078d..439d89b25ae096a6bf49c73d929aac25a7a4e3d2
@@@ -13,7 -13,8 +13,8 @@@ drm-y       :=        drm_auth.o drm_bufs.o dr
                drm_trace_points.o drm_global.o drm_prime.o \
                drm_rect.o drm_vma_manager.o drm_flip_work.o \
                drm_modeset_lock.o drm_atomic.o drm_bridge.o \
-               drm_framebuffer.o drm_connector.o drm_blend.o
+               drm_framebuffer.o drm_connector.o drm_blend.o \
+               drm_encoder.o drm_mode_object.o drm_property.o
  
  drm-$(CONFIG_COMPAT) += drm_ioc32.o
  drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
@@@ -47,7 -48,7 +48,7 @@@ obj-$(CONFIG_DRM_RADEON)+= radeon
  obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/
  obj-$(CONFIG_DRM_MGA) += mga/
  obj-$(CONFIG_DRM_I810)        += i810/
 -obj-$(CONFIG_DRM_I915)  += i915/
 +obj-$(CONFIG_DRM_I915)        += i915/
  obj-$(CONFIG_DRM_MGAG200) += mgag200/
  obj-$(CONFIG_DRM_VC4)  += vc4/
  obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus/
index 7b21281c4b78ca1b11b9f741360aebd9a00b94fe,b95c48acfa5b058f266f9f582678eb83ba9470bd..a33dab27bb0d27a9923ef1812b0a909aab37bae5
@@@ -54,177 -54,9 +54,9 @@@ static const struct drm_prop_enum_list 
        { DRM_PLANE_TYPE_CURSOR, "Cursor" },
  };
  
- static const struct drm_prop_enum_list drm_encoder_enum_list[] = {
-       { DRM_MODE_ENCODER_NONE, "None" },
-       { DRM_MODE_ENCODER_DAC, "DAC" },
-       { DRM_MODE_ENCODER_TMDS, "TMDS" },
-       { DRM_MODE_ENCODER_LVDS, "LVDS" },
-       { DRM_MODE_ENCODER_TVDAC, "TV" },
-       { DRM_MODE_ENCODER_VIRTUAL, "Virtual" },
-       { DRM_MODE_ENCODER_DSI, "DSI" },
-       { DRM_MODE_ENCODER_DPMST, "DP MST" },
-       { DRM_MODE_ENCODER_DPI, "DPI" },
- };
  /*
   * Optional properties
   */
- /*
-  * Internal function to assign a slot in the object idr and optionally
-  * register the object into the idr.
-  */
- int drm_mode_object_get_reg(struct drm_device *dev,
-                           struct drm_mode_object *obj,
-                           uint32_t obj_type,
-                           bool register_obj,
-                           void (*obj_free_cb)(struct kref *kref))
- {
-       int ret;
-       mutex_lock(&dev->mode_config.idr_mutex);
-       ret = idr_alloc(&dev->mode_config.crtc_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL);
-       if (ret >= 0) {
-               /*
-                * Set up the object linking under the protection of the idr
-                * lock so that other users can't see inconsistent state.
-                */
-               obj->id = ret;
-               obj->type = obj_type;
-               if (obj_free_cb) {
-                       obj->free_cb = obj_free_cb;
-                       kref_init(&obj->refcount);
-               }
-       }
-       mutex_unlock(&dev->mode_config.idr_mutex);
-       return ret < 0 ? ret : 0;
- }
- /**
-  * drm_mode_object_get - allocate a new modeset identifier
-  * @dev: DRM device
-  * @obj: object pointer, used to generate unique ID
-  * @obj_type: object type
-  *
-  * Create a unique identifier based on @ptr in @dev's identifier space.  Used
-  * for tracking modes, CRTCs and connectors. Note that despite the _get postfix
-  * modeset identifiers are _not_ reference counted. Hence don't use this for
-  * reference counted modeset objects like framebuffers.
-  *
-  * Returns:
-  * Zero on success, error code on failure.
-  */
- int drm_mode_object_get(struct drm_device *dev,
-                       struct drm_mode_object *obj, uint32_t obj_type)
- {
-       return drm_mode_object_get_reg(dev, obj, obj_type, true, NULL);
- }
- void drm_mode_object_register(struct drm_device *dev,
-                             struct drm_mode_object *obj)
- {
-       mutex_lock(&dev->mode_config.idr_mutex);
-       idr_replace(&dev->mode_config.crtc_idr, obj, obj->id);
-       mutex_unlock(&dev->mode_config.idr_mutex);
- }
- /**
-  * drm_mode_object_unregister - free a modeset identifer
-  * @dev: DRM device
-  * @object: object to free
-  *
-  * Free @id from @dev's unique identifier pool.
-  * This function can be called multiple times, and guards against
-  * multiple removals.
-  * These modeset identifiers are _not_ reference counted. Hence don't use this
-  * for reference counted modeset objects like framebuffers.
-  */
- void drm_mode_object_unregister(struct drm_device *dev,
-                        struct drm_mode_object *object)
- {
-       mutex_lock(&dev->mode_config.idr_mutex);
-       if (object->id) {
-               idr_remove(&dev->mode_config.crtc_idr, object->id);
-               object->id = 0;
-       }
-       mutex_unlock(&dev->mode_config.idr_mutex);
- }
- struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
-                                              uint32_t id, uint32_t type)
- {
-       struct drm_mode_object *obj = NULL;
-       mutex_lock(&dev->mode_config.idr_mutex);
-       obj = idr_find(&dev->mode_config.crtc_idr, id);
-       if (obj && type != DRM_MODE_OBJECT_ANY && obj->type != type)
-               obj = NULL;
-       if (obj && obj->id != id)
-               obj = NULL;
-       if (obj && obj->free_cb) {
-               if (!kref_get_unless_zero(&obj->refcount))
-                       obj = NULL;
-       }
-       mutex_unlock(&dev->mode_config.idr_mutex);
-       return obj;
- }
- /**
-  * drm_mode_object_find - look up a drm object with static lifetime
-  * @dev: drm device
-  * @id: id of the mode object
-  * @type: type of the mode object
-  *
-  * This function is used to look up a modeset object. It will acquire a
-  * reference for reference counted objects. This reference must be dropped again
-  * by callind drm_mode_object_unreference().
-  */
- struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
-               uint32_t id, uint32_t type)
- {
-       struct drm_mode_object *obj = NULL;
-       obj = __drm_mode_object_find(dev, id, type);
-       return obj;
- }
- EXPORT_SYMBOL(drm_mode_object_find);
- /**
-  * drm_mode_object_unreference - decr the object refcnt
-  * @obj: mode_object
-  *
-  * This functions decrements the object's refcount if it is a refcounted modeset
-  * object. It is a no-op on any other object. This is used to drop references
-  * acquired with drm_mode_object_reference().
-  */
- void drm_mode_object_unreference(struct drm_mode_object *obj)
- {
-       if (obj->free_cb) {
-               DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
-               kref_put(&obj->refcount, obj->free_cb);
-       }
- }
- EXPORT_SYMBOL(drm_mode_object_unreference);
- /**
-  * drm_mode_object_reference - incr the object refcnt
-  * @obj: mode_object
-  *
-  * This functions increments the object's refcount if it is a refcounted modeset
-  * object. It is a no-op on any other object. References should be dropped again
-  * by calling drm_mode_object_unreference().
-  */
- void drm_mode_object_reference(struct drm_mode_object *obj)
- {
-       if (obj->free_cb) {
-               DRM_DEBUG("OBJ ID: %d (%d)\n", obj->id, atomic_read(&obj->refcount.refcount));
-               kref_get(&obj->refcount);
-       }
- }
- EXPORT_SYMBOL(drm_mode_object_reference);
  /**
   * drm_crtc_force_disable - Forcibly turn off a CRTC
   * @crtc: CRTC to turn off
@@@ -419,117 -251,6 +251,6 @@@ void drm_crtc_cleanup(struct drm_crtc *
  }
  EXPORT_SYMBOL(drm_crtc_cleanup);
  
- static int drm_encoder_register_all(struct drm_device *dev)
- {
-       struct drm_encoder *encoder;
-       int ret = 0;
-       drm_for_each_encoder(encoder, dev) {
-               if (encoder->funcs->late_register)
-                       ret = encoder->funcs->late_register(encoder);
-               if (ret)
-                       return ret;
-       }
-       return 0;
- }
- static void drm_encoder_unregister_all(struct drm_device *dev)
- {
-       struct drm_encoder *encoder;
-       drm_for_each_encoder(encoder, dev) {
-               if (encoder->funcs->early_unregister)
-                       encoder->funcs->early_unregister(encoder);
-       }
- }
- /**
-  * drm_encoder_init - Init a preallocated encoder
-  * @dev: drm device
-  * @encoder: the encoder to init
-  * @funcs: callbacks for this encoder
-  * @encoder_type: user visible type of the encoder
-  * @name: printf style format string for the encoder name, or NULL for default name
-  *
-  * Initialises a preallocated encoder. Encoder should be
-  * subclassed as part of driver encoder objects.
-  *
-  * Returns:
-  * Zero on success, error code on failure.
-  */
- int drm_encoder_init(struct drm_device *dev,
-                     struct drm_encoder *encoder,
-                     const struct drm_encoder_funcs *funcs,
-                     int encoder_type, const char *name, ...)
- {
-       int ret;
-       drm_modeset_lock_all(dev);
-       ret = drm_mode_object_get(dev, &encoder->base, DRM_MODE_OBJECT_ENCODER);
-       if (ret)
-               goto out_unlock;
-       encoder->dev = dev;
-       encoder->encoder_type = encoder_type;
-       encoder->funcs = funcs;
-       if (name) {
-               va_list ap;
-               va_start(ap, name);
-               encoder->name = kvasprintf(GFP_KERNEL, name, ap);
-               va_end(ap);
-       } else {
-               encoder->name = kasprintf(GFP_KERNEL, "%s-%d",
-                                         drm_encoder_enum_list[encoder_type].name,
-                                         encoder->base.id);
-       }
-       if (!encoder->name) {
-               ret = -ENOMEM;
-               goto out_put;
-       }
-       list_add_tail(&encoder->head, &dev->mode_config.encoder_list);
-       encoder->index = dev->mode_config.num_encoder++;
- out_put:
-       if (ret)
-               drm_mode_object_unregister(dev, &encoder->base);
- out_unlock:
-       drm_modeset_unlock_all(dev);
-       return ret;
- }
- EXPORT_SYMBOL(drm_encoder_init);
- /**
-  * drm_encoder_cleanup - cleans up an initialised encoder
-  * @encoder: encoder to cleanup
-  *
-  * Cleans up the encoder but doesn't free the object.
-  */
- void drm_encoder_cleanup(struct drm_encoder *encoder)
- {
-       struct drm_device *dev = encoder->dev;
-       /* Note that the encoder_list is considered to be static; should we
-        * remove the drm_encoder at runtime we would have to decrement all
-        * the indices on the drm_encoder after us in the encoder_list.
-        */
-       drm_modeset_lock_all(dev);
-       drm_mode_object_unregister(dev, &encoder->base);
-       kfree(encoder->name);
-       list_del(&encoder->head);
-       dev->mode_config.num_encoder--;
-       drm_modeset_unlock_all(dev);
-       memset(encoder, 0, sizeof(*encoder));
- }
- EXPORT_SYMBOL(drm_encoder_cleanup);
  static unsigned int drm_num_planes(struct drm_device *dev)
  {
        unsigned int num = 0;
@@@ -1133,115 -854,6 +854,6 @@@ int drm_mode_getcrtc(struct drm_device 
        return 0;
  }
  
- /* helper for getconnector and getproperties ioctls */
- int drm_mode_object_get_properties(struct drm_mode_object *obj, bool atomic,
-                                  uint32_t __user *prop_ptr,
-                                  uint64_t __user *prop_values,
-                                  uint32_t *arg_count_props)
- {
-       int props_count;
-       int i, ret, copied;
-       props_count = obj->properties->count;
-       if (!atomic)
-               props_count -= obj->properties->atomic_count;
-       if ((*arg_count_props >= props_count) && props_count) {
-               for (i = 0, copied = 0; copied < props_count; i++) {
-                       struct drm_property *prop = obj->properties->properties[i];
-                       uint64_t val;
-                       if ((prop->flags & DRM_MODE_PROP_ATOMIC) && !atomic)
-                               continue;
-                       ret = drm_object_property_get_value(obj, prop, &val);
-                       if (ret)
-                               return ret;
-                       if (put_user(prop->base.id, prop_ptr + copied))
-                               return -EFAULT;
-                       if (put_user(val, prop_values + copied))
-                               return -EFAULT;
-                       copied++;
-               }
-       }
-       *arg_count_props = props_count;
-       return 0;
- }
- static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
- {
-       struct drm_connector *connector;
-       struct drm_device *dev = encoder->dev;
-       bool uses_atomic = false;
-       /* For atomic drivers only state objects are synchronously updated and
-        * protected by modeset locks, so check those first. */
-       drm_for_each_connector(connector, dev) {
-               if (!connector->state)
-                       continue;
-               uses_atomic = true;
-               if (connector->state->best_encoder != encoder)
-                       continue;
-               return connector->state->crtc;
-       }
-       /* Don't return stale data (e.g. pending async disable). */
-       if (uses_atomic)
-               return NULL;
-       return encoder->crtc;
- }
- /**
-  * drm_mode_getencoder - get encoder configuration
-  * @dev: drm device for the ioctl
-  * @data: data pointer for the ioctl
-  * @file_priv: drm file for the ioctl call
-  *
-  * Construct a encoder configuration structure to return to the user.
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_getencoder(struct drm_device *dev, void *data,
-                       struct drm_file *file_priv)
- {
-       struct drm_mode_get_encoder *enc_resp = data;
-       struct drm_encoder *encoder;
-       struct drm_crtc *crtc;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       encoder = drm_encoder_find(dev, enc_resp->encoder_id);
-       if (!encoder)
-               return -ENOENT;
-       drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
-       crtc = drm_encoder_get_crtc(encoder);
-       if (crtc)
-               enc_resp->crtc_id = crtc->base.id;
-       else
-               enc_resp->crtc_id = 0;
-       drm_modeset_unlock(&dev->mode_config.connection_mutex);
-       enc_resp->encoder_type = encoder->encoder_type;
-       enc_resp->encoder_id = encoder->base.id;
-       enc_resp->possible_crtcs = encoder->possible_crtcs;
-       enc_resp->possible_clones = encoder->possible_clones;
-       return 0;
- }
  /**
   * drm_mode_getplane_res - enumerate all plane resources
   * @dev: DRM device
@@@ -2059,1231 -1671,50 +1671,50 @@@ int drm_mode_cursor2_ioctl(struct drm_d
        return drm_mode_cursor_common(dev, req, file_priv);
  }
  
- /**
-  * drm_mode_legacy_fb_format - compute drm fourcc code from legacy description
-  * @bpp: bits per pixels
-  * @depth: bit depth per pixel
-  *
-  * Computes a drm fourcc pixel format code for the given @bpp/@depth values.
-  * Useful in fbdev emulation code, since that deals in those values.
-  */
- uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
- {
-       uint32_t fmt;
-       switch (bpp) {
-       case 8:
-               fmt = DRM_FORMAT_C8;
-               break;
-       case 16:
-               if (depth == 15)
-                       fmt = DRM_FORMAT_XRGB1555;
-               else
-                       fmt = DRM_FORMAT_RGB565;
-               break;
-       case 24:
-               fmt = DRM_FORMAT_RGB888;
-               break;
-       case 32:
-               if (depth == 24)
-                       fmt = DRM_FORMAT_XRGB8888;
-               else if (depth == 30)
-                       fmt = DRM_FORMAT_XRGB2101010;
-               else
-                       fmt = DRM_FORMAT_ARGB8888;
-               break;
-       default:
-               DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
-               fmt = DRM_FORMAT_XRGB8888;
-               break;
-       }
-       return fmt;
- }
- EXPORT_SYMBOL(drm_mode_legacy_fb_format);
- static bool drm_property_type_valid(struct drm_property *property)
- {
-       if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
-               return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
-       return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
- }
- /**
-  * drm_property_create - create a new property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @num_values: number of pre-defined values
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * Note that the DRM core keeps a per-device list of properties and that, if
-  * drm_mode_config_cleanup() is called, it will destroy all properties created
-  * by the driver.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create(struct drm_device *dev, int flags,
-                                        const char *name, int num_values)
- {
-       struct drm_property *property = NULL;
-       int ret;
-       property = kzalloc(sizeof(struct drm_property), GFP_KERNEL);
-       if (!property)
-               return NULL;
-       property->dev = dev;
-       if (num_values) {
-               property->values = kcalloc(num_values, sizeof(uint64_t),
-                                          GFP_KERNEL);
-               if (!property->values)
-                       goto fail;
-       }
-       ret = drm_mode_object_get(dev, &property->base, DRM_MODE_OBJECT_PROPERTY);
-       if (ret)
-               goto fail;
-       property->flags = flags;
-       property->num_values = num_values;
-       INIT_LIST_HEAD(&property->enum_list);
-       if (name) {
-               strncpy(property->name, name, DRM_PROP_NAME_LEN);
-               property->name[DRM_PROP_NAME_LEN-1] = '\0';
-       }
-       list_add_tail(&property->head, &dev->mode_config.property_list);
-       WARN_ON(!drm_property_type_valid(property));
-       return property;
- fail:
-       kfree(property->values);
-       kfree(property);
-       return NULL;
- }
- EXPORT_SYMBOL(drm_property_create);
- /**
-  * drm_property_create_enum - create a new enumeration property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @props: enumeration lists with property values
-  * @num_values: number of pre-defined values
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * Userspace is only allowed to set one of the predefined values for enumeration
-  * properties.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
-                                        const char *name,
-                                        const struct drm_prop_enum_list *props,
-                                        int num_values)
+ int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
+                              struct drm_property *property,
+                              uint64_t value)
  {
-       struct drm_property *property;
-       int i, ret;
-       flags |= DRM_MODE_PROP_ENUM;
-       property = drm_property_create(dev, flags, name, num_values);
-       if (!property)
-               return NULL;
+       int ret = -EINVAL;
+       struct drm_crtc *crtc = obj_to_crtc(obj);
  
-       for (i = 0; i < num_values; i++) {
-               ret = drm_property_add_enum(property, i,
-                                     props[i].type,
-                                     props[i].name);
-               if (ret) {
-                       drm_property_destroy(dev, property);
-                       return NULL;
-               }
-       }
+       if (crtc->funcs->set_property)
+               ret = crtc->funcs->set_property(crtc, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
  
-       return property;
+       return ret;
  }
- EXPORT_SYMBOL(drm_property_create_enum);
  
  /**
-  * drm_property_create_bitmask - create a new bitmask property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @props: enumeration lists with property bitflags
-  * @num_props: size of the @props array
-  * @supported_bits: bitmask of all supported enumeration values
-  *
-  * This creates a new bitmask drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
+  * 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
   *
-  * Compared to plain enumeration properties userspace is allowed to set any
-  * or'ed together combination of the predefined property bitflag values
+  * 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:
-  * A pointer to the newly created property on success, NULL on failure.
+  * Zero on success, error code on failure.
   */
- struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
-                                        int flags, const char *name,
-                                        const struct drm_prop_enum_list *props,
-                                        int num_props,
-                                        uint64_t supported_bits)
+ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
+                               struct drm_property *property,
+                               uint64_t value)
  {
-       struct drm_property *property;
-       int i, ret, index = 0;
-       int num_values = hweight64(supported_bits);
-       flags |= DRM_MODE_PROP_BITMASK;
-       property = drm_property_create(dev, flags, name, num_values);
-       if (!property)
-               return NULL;
-       for (i = 0; i < num_props; i++) {
-               if (!(supported_bits & (1ULL << props[i].type)))
-                       continue;
-               if (WARN_ON(index >= num_values)) {
-                       drm_property_destroy(dev, property);
-                       return NULL;
-               }
+       int ret = -EINVAL;
+       struct drm_mode_object *obj = &plane->base;
  
-               ret = drm_property_add_enum(property, index++,
-                                     props[i].type,
-                                     props[i].name);
-               if (ret) {
-                       drm_property_destroy(dev, property);
-                       return NULL;
-               }
-       }
+       if (plane->funcs->set_property)
+               ret = plane->funcs->set_property(plane, property, value);
+       if (!ret)
+               drm_object_property_set_value(obj, property, value);
  
-       return property;
- }
- EXPORT_SYMBOL(drm_property_create_bitmask);
- static struct drm_property *property_create_range(struct drm_device *dev,
-                                        int flags, const char *name,
-                                        uint64_t min, uint64_t max)
- {
-       struct drm_property *property;
-       property = drm_property_create(dev, flags, name, 2);
-       if (!property)
-               return NULL;
-       property->values[0] = min;
-       property->values[1] = max;
-       return property;
- }
- /**
-  * drm_property_create_range - create a new unsigned ranged property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @min: minimum value of the property
-  * @max: maximum value of the property
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * Userspace is allowed to set any unsigned integer value in the (min, max)
-  * range inclusive.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
-                                        const char *name,
-                                        uint64_t min, uint64_t max)
- {
-       return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
-                       name, min, max);
- }
- EXPORT_SYMBOL(drm_property_create_range);
- /**
-  * drm_property_create_signed_range - create a new signed ranged property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @min: minimum value of the property
-  * @max: maximum value of the property
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * Userspace is allowed to set any signed integer value in the (min, max)
-  * range inclusive.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
-                                        int flags, const char *name,
-                                        int64_t min, int64_t max)
- {
-       return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
-                       name, I642U64(min), I642U64(max));
- }
- EXPORT_SYMBOL(drm_property_create_signed_range);
- /**
-  * drm_property_create_object - create a new object property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  * @type: object type from DRM_MODE_OBJECT_* defines
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * Userspace is only allowed to set this to any property value of the given
-  * @type. Only useful for atomic properties, which is enforced.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create_object(struct drm_device *dev,
-                                        int flags, const char *name, uint32_t type)
- {
-       struct drm_property *property;
-       flags |= DRM_MODE_PROP_OBJECT;
-       if (WARN_ON(!(flags & DRM_MODE_PROP_ATOMIC)))
-               return NULL;
-       property = drm_property_create(dev, flags, name, 1);
-       if (!property)
-               return NULL;
-       property->values[0] = type;
-       return property;
- }
- EXPORT_SYMBOL(drm_property_create_object);
- /**
-  * drm_property_create_bool - create a new boolean property type
-  * @dev: drm device
-  * @flags: flags specifying the property type
-  * @name: name of the property
-  *
-  * This creates a new generic drm property which can then be attached to a drm
-  * object with drm_object_attach_property. The returned property object must be
-  * freed with drm_property_destroy.
-  *
-  * This is implemented as a ranged property with only {0, 1} as valid values.
-  *
-  * Returns:
-  * A pointer to the newly created property on success, NULL on failure.
-  */
- struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
-                                        const char *name)
- {
-       return drm_property_create_range(dev, flags, name, 0, 1);
- }
- EXPORT_SYMBOL(drm_property_create_bool);
- /**
-  * drm_property_add_enum - add a possible value to an enumeration property
-  * @property: enumeration property to change
-  * @index: index of the new enumeration
-  * @value: value of the new enumeration
-  * @name: symbolic name of the new enumeration
-  *
-  * This functions adds enumerations to a property.
-  *
-  * It's use is deprecated, drivers should use one of the more specific helpers
-  * to directly create the property with all enumerations already attached.
-  *
-  * Returns:
-  * Zero on success, error code on failure.
-  */
- int drm_property_add_enum(struct drm_property *property, int index,
-                         uint64_t value, const char *name)
- {
-       struct drm_property_enum *prop_enum;
-       if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-                       drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
-               return -EINVAL;
-       /*
-        * Bitmask enum properties have the additional constraint of values
-        * from 0 to 63
-        */
-       if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
-                       (value > 63))
-               return -EINVAL;
-       if (!list_empty(&property->enum_list)) {
-               list_for_each_entry(prop_enum, &property->enum_list, head) {
-                       if (prop_enum->value == value) {
-                               strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
-                               prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
-                               return 0;
-                       }
-               }
-       }
-       prop_enum = kzalloc(sizeof(struct drm_property_enum), GFP_KERNEL);
-       if (!prop_enum)
-               return -ENOMEM;
-       strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
-       prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
-       prop_enum->value = value;
-       property->values[index] = value;
-       list_add_tail(&prop_enum->head, &property->enum_list);
-       return 0;
- }
- EXPORT_SYMBOL(drm_property_add_enum);
- /**
-  * drm_property_destroy - destroy a drm property
-  * @dev: drm device
-  * @property: property to destry
-  *
-  * This function frees a property including any attached resources like
-  * enumeration values.
-  */
- void drm_property_destroy(struct drm_device *dev, struct drm_property *property)
- {
-       struct drm_property_enum *prop_enum, *pt;
-       list_for_each_entry_safe(prop_enum, pt, &property->enum_list, head) {
-               list_del(&prop_enum->head);
-               kfree(prop_enum);
-       }
-       if (property->num_values)
-               kfree(property->values);
-       drm_mode_object_unregister(dev, &property->base);
-       list_del(&property->head);
-       kfree(property);
- }
- EXPORT_SYMBOL(drm_property_destroy);
- /**
-  * drm_object_attach_property - attach a property to a modeset object
-  * @obj: drm modeset object
-  * @property: property to attach
-  * @init_val: initial value of the property
-  *
-  * This attaches the given property to the modeset object with the given initial
-  * value. Currently this function cannot fail since the properties are stored in
-  * a statically sized array.
-  */
- void drm_object_attach_property(struct drm_mode_object *obj,
-                               struct drm_property *property,
-                               uint64_t init_val)
- {
-       int count = obj->properties->count;
-       if (count == DRM_OBJECT_MAX_PROPERTY) {
-               WARN(1, "Failed to attach object property (type: 0x%x). Please "
-                       "increase DRM_OBJECT_MAX_PROPERTY by 1 for each time "
-                       "you see this message on the same object type.\n",
-                       obj->type);
-               return;
-       }
-       obj->properties->properties[count] = property;
-       obj->properties->values[count] = init_val;
-       obj->properties->count++;
-       if (property->flags & DRM_MODE_PROP_ATOMIC)
-               obj->properties->atomic_count++;
- }
- EXPORT_SYMBOL(drm_object_attach_property);
- /**
-  * drm_object_property_set_value - set the value of a property
-  * @obj: drm mode object to set property value for
-  * @property: property to set
-  * @val: value the property should be set to
-  *
-  * This functions sets a given property on a given object. This function only
-  * changes the software state of the property, it does not call into the
-  * driver's ->set_property callback.
-  *
-  * Returns:
-  * Zero on success, error code on failure.
-  */
- int drm_object_property_set_value(struct drm_mode_object *obj,
-                                 struct drm_property *property, uint64_t val)
- {
-       int i;
-       for (i = 0; i < obj->properties->count; i++) {
-               if (obj->properties->properties[i] == property) {
-                       obj->properties->values[i] = val;
-                       return 0;
-               }
-       }
-       return -EINVAL;
- }
- EXPORT_SYMBOL(drm_object_property_set_value);
- /**
-  * drm_object_property_get_value - retrieve the value of a property
-  * @obj: drm mode object to get property value from
-  * @property: property to retrieve
-  * @val: storage for the property value
-  *
-  * This function retrieves the softare state of the given property for the given
-  * property. Since there is no driver callback to retrieve the current property
-  * value this might be out of sync with the hardware, depending upon the driver
-  * and property.
-  *
-  * Returns:
-  * Zero on success, error code on failure.
-  */
- int drm_object_property_get_value(struct drm_mode_object *obj,
-                                 struct drm_property *property, uint64_t *val)
- {
-       int i;
-       /* read-only properties bypass atomic mechanism and still store
-        * their value in obj->properties->values[].. mostly to avoid
-        * having to deal w/ EDID and similar props in atomic paths:
-        */
-       if (drm_core_check_feature(property->dev, DRIVER_ATOMIC) &&
-                       !(property->flags & DRM_MODE_PROP_IMMUTABLE))
-               return drm_atomic_get_property(obj, property, val);
-       for (i = 0; i < obj->properties->count; i++) {
-               if (obj->properties->properties[i] == property) {
-                       *val = obj->properties->values[i];
-                       return 0;
-               }
-       }
-       return -EINVAL;
- }
- EXPORT_SYMBOL(drm_object_property_get_value);
- /**
-  * drm_mode_getproperty_ioctl - get the property metadata
-  * @dev: DRM device
-  * @data: ioctl data
-  * @file_priv: DRM file info
-  *
-  * This function retrieves the metadata for a given property, like the different
-  * possible values for an enum property or the limits for a range property.
-  *
-  * Blob properties are special
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_getproperty_ioctl(struct drm_device *dev,
-                              void *data, struct drm_file *file_priv)
- {
-       struct drm_mode_get_property *out_resp = data;
-       struct drm_property *property;
-       int enum_count = 0;
-       int value_count = 0;
-       int ret = 0, i;
-       int copied;
-       struct drm_property_enum *prop_enum;
-       struct drm_mode_property_enum __user *enum_ptr;
-       uint64_t __user *values_ptr;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       drm_modeset_lock_all(dev);
-       property = drm_property_find(dev, out_resp->prop_id);
-       if (!property) {
-               ret = -ENOENT;
-               goto done;
-       }
-       if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-                       drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-               list_for_each_entry(prop_enum, &property->enum_list, head)
-                       enum_count++;
-       }
-       value_count = property->num_values;
-       strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
-       out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
-       out_resp->flags = property->flags;
-       if ((out_resp->count_values >= value_count) && value_count) {
-               values_ptr = (uint64_t __user *)(unsigned long)out_resp->values_ptr;
-               for (i = 0; i < value_count; i++) {
-                       if (copy_to_user(values_ptr + i, &property->values[i], sizeof(uint64_t))) {
-                               ret = -EFAULT;
-                               goto done;
-                       }
-               }
-       }
-       out_resp->count_values = value_count;
-       if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
-                       drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-               if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
-                       copied = 0;
-                       enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
-                       list_for_each_entry(prop_enum, &property->enum_list, head) {
-                               if (copy_to_user(&enum_ptr[copied].value, &prop_enum->value, sizeof(uint64_t))) {
-                                       ret = -EFAULT;
-                                       goto done;
-                               }
-                               if (copy_to_user(&enum_ptr[copied].name,
-                                                &prop_enum->name, DRM_PROP_NAME_LEN)) {
-                                       ret = -EFAULT;
-                                       goto done;
-                               }
-                               copied++;
-                       }
-               }
-               out_resp->count_enum_blobs = enum_count;
-       }
-       /*
-        * NOTE: The idea seems to have been to use this to read all the blob
-        * property values. But nothing ever added them to the corresponding
-        * list, userspace always used the special-purpose get_blob ioctl to
-        * read the value for a blob property. It also doesn't make a lot of
-        * sense to return values here when everything else is just metadata for
-        * the property itself.
-        */
-       if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-               out_resp->count_enum_blobs = 0;
- done:
-       drm_modeset_unlock_all(dev);
-       return ret;
- }
- static void drm_property_free_blob(struct kref *kref)
- {
-       struct drm_property_blob *blob =
-               container_of(kref, struct drm_property_blob, base.refcount);
-       mutex_lock(&blob->dev->mode_config.blob_lock);
-       list_del(&blob->head_global);
-       mutex_unlock(&blob->dev->mode_config.blob_lock);
-       drm_mode_object_unregister(blob->dev, &blob->base);
-       kfree(blob);
- }
- /**
-  * drm_property_create_blob - Create new blob property
-  *
-  * Creates a new blob property for a specified DRM device, optionally
-  * copying data.
-  *
-  * @dev: DRM device to create property for
-  * @length: Length to allocate for blob data
-  * @data: If specified, copies data into blob
-  *
-  * Returns:
-  * New blob property with a single reference on success, or an ERR_PTR
-  * value on failure.
-  */
- struct drm_property_blob *
- drm_property_create_blob(struct drm_device *dev, size_t length,
-                        const void *data)
- {
-       struct drm_property_blob *blob;
-       int ret;
-       if (!length || length > ULONG_MAX - sizeof(struct drm_property_blob))
-               return ERR_PTR(-EINVAL);
-       blob = kzalloc(sizeof(struct drm_property_blob)+length, GFP_KERNEL);
-       if (!blob)
-               return ERR_PTR(-ENOMEM);
-       /* This must be explicitly initialised, so we can safely call list_del
-        * on it in the removal handler, even if it isn't in a file list. */
-       INIT_LIST_HEAD(&blob->head_file);
-       blob->length = length;
-       blob->dev = dev;
-       if (data)
-               memcpy(blob->data, data, length);
-       ret = drm_mode_object_get_reg(dev, &blob->base, DRM_MODE_OBJECT_BLOB,
-                                     true, drm_property_free_blob);
-       if (ret) {
-               kfree(blob);
-               return ERR_PTR(-EINVAL);
-       }
-       mutex_lock(&dev->mode_config.blob_lock);
-       list_add_tail(&blob->head_global,
-                     &dev->mode_config.property_blob_list);
-       mutex_unlock(&dev->mode_config.blob_lock);
-       return blob;
- }
- EXPORT_SYMBOL(drm_property_create_blob);
- /**
-  * drm_property_unreference_blob - Unreference a blob property
-  *
-  * Drop a reference on a blob property. May free the object.
-  *
-  * @blob: Pointer to blob property
-  */
- void drm_property_unreference_blob(struct drm_property_blob *blob)
- {
-       if (!blob)
-               return;
-       drm_mode_object_unreference(&blob->base);
- }
- EXPORT_SYMBOL(drm_property_unreference_blob);
- /**
-  * drm_property_destroy_user_blobs - destroy all blobs created by this client
-  * @dev:       DRM device
-  * @file_priv: destroy all blobs owned by this file handle
-  */
- void drm_property_destroy_user_blobs(struct drm_device *dev,
-                                    struct drm_file *file_priv)
- {
-       struct drm_property_blob *blob, *bt;
-       /*
-        * When the file gets released that means no one else can access the
-        * blob list any more, so no need to grab dev->blob_lock.
-        */
-       list_for_each_entry_safe(blob, bt, &file_priv->blobs, head_file) {
-               list_del_init(&blob->head_file);
-               drm_property_unreference_blob(blob);
-       }
- }
- /**
-  * drm_property_reference_blob - Take a reference on an existing property
-  *
-  * Take a new reference on an existing blob property.
-  *
-  * @blob: Pointer to blob property
-  */
- struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob)
- {
-       drm_mode_object_reference(&blob->base);
-       return blob;
- }
- EXPORT_SYMBOL(drm_property_reference_blob);
- /**
-  * drm_property_lookup_blob - look up a blob property and take a reference
-  * @dev: drm device
-  * @id: id of the blob property
-  *
-  * If successful, this takes an additional reference to the blob property.
-  * callers need to make sure to eventually unreference the returned property
-  * again, using @drm_property_unreference_blob.
-  */
- struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
-                                                  uint32_t id)
- {
-       struct drm_mode_object *obj;
-       struct drm_property_blob *blob = NULL;
-       obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
-       if (obj)
-               blob = obj_to_blob(obj);
-       return blob;
- }
- EXPORT_SYMBOL(drm_property_lookup_blob);
- /**
-  * drm_property_replace_global_blob - atomically replace existing blob property
-  * @dev: drm device
-  * @replace: location of blob property pointer to be replaced
-  * @length: length of data for new blob, or 0 for no data
-  * @data: content for new blob, or NULL for no data
-  * @obj_holds_id: optional object for property holding blob ID
-  * @prop_holds_id: optional property holding blob ID
-  * @return 0 on success or error on failure
-  *
-  * This function will atomically replace a global property in the blob list,
-  * optionally updating a property which holds the ID of that property. It is
-  * guaranteed to be atomic: no caller will be allowed to see intermediate
-  * results, and either the entire operation will succeed and clean up the
-  * previous property, or it will fail and the state will be unchanged.
-  *
-  * If length is 0 or data is NULL, no new blob will be created, and the holding
-  * property, if specified, will be set to 0.
-  *
-  * Access to the replace pointer is assumed to be protected by the caller, e.g.
-  * by holding the relevant modesetting object lock for its parent.
-  *
-  * For example, a drm_connector has a 'PATH' property, which contains the ID
-  * of a blob property with the value of the MST path information. Calling this
-  * function with replace pointing to the connector's path_blob_ptr, length and
-  * data set for the new path information, obj_holds_id set to the connector's
-  * base object, and prop_holds_id set to the path property name, will perform
-  * a completely atomic update. The access to path_blob_ptr is protected by the
-  * caller holding a lock on the connector.
-  */
- int drm_property_replace_global_blob(struct drm_device *dev,
-                                    struct drm_property_blob **replace,
-                                    size_t length,
-                                    const void *data,
-                                    struct drm_mode_object *obj_holds_id,
-                                    struct drm_property *prop_holds_id)
- {
-       struct drm_property_blob *new_blob = NULL;
-       struct drm_property_blob *old_blob = NULL;
-       int ret;
-       WARN_ON(replace == NULL);
-       old_blob = *replace;
-       if (length && data) {
-               new_blob = drm_property_create_blob(dev, length, data);
-               if (IS_ERR(new_blob))
-                       return PTR_ERR(new_blob);
-       }
-       /* This does not need to be synchronised with blob_lock, as the
-        * get_properties ioctl locks all modesetting objects, and
-        * obj_holds_id must be locked before calling here, so we cannot
-        * have its value out of sync with the list membership modified
-        * below under blob_lock. */
-       if (obj_holds_id) {
-               ret = drm_object_property_set_value(obj_holds_id,
-                                                   prop_holds_id,
-                                                   new_blob ?
-                                                       new_blob->base.id : 0);
-               if (ret != 0)
-                       goto err_created;
-       }
-       drm_property_unreference_blob(old_blob);
-       *replace = new_blob;
-       return 0;
- err_created:
-       drm_property_unreference_blob(new_blob);
-       return ret;
- }
- EXPORT_SYMBOL(drm_property_replace_global_blob);
- /**
-  * drm_mode_getblob_ioctl - get the contents of a blob property value
-  * @dev: DRM device
-  * @data: ioctl data
-  * @file_priv: DRM file info
-  *
-  * This function retrieves the contents of a blob property. The value stored in
-  * an object's blob property is just a normal modeset object id.
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_getblob_ioctl(struct drm_device *dev,
-                          void *data, struct drm_file *file_priv)
- {
-       struct drm_mode_get_blob *out_resp = data;
-       struct drm_property_blob *blob;
-       int ret = 0;
-       void __user *blob_ptr;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       blob = drm_property_lookup_blob(dev, out_resp->blob_id);
-       if (!blob)
-               return -ENOENT;
-       if (out_resp->length == blob->length) {
-               blob_ptr = (void __user *)(unsigned long)out_resp->data;
-               if (copy_to_user(blob_ptr, blob->data, blob->length)) {
-                       ret = -EFAULT;
-                       goto unref;
-               }
-       }
-       out_resp->length = blob->length;
- unref:
-       drm_property_unreference_blob(blob);
-       return ret;
- }
- /**
-  * drm_mode_createblob_ioctl - create a new blob property
-  * @dev: DRM device
-  * @data: ioctl data
-  * @file_priv: DRM file info
-  *
-  * This function creates a new blob property with user-defined values. In order
-  * to give us sensible validation and checking when creating, rather than at
-  * every potential use, we also require a type to be provided upfront.
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_createblob_ioctl(struct drm_device *dev,
-                             void *data, struct drm_file *file_priv)
- {
-       struct drm_mode_create_blob *out_resp = data;
-       struct drm_property_blob *blob;
-       void __user *blob_ptr;
-       int ret = 0;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       blob = drm_property_create_blob(dev, out_resp->length, NULL);
-       if (IS_ERR(blob))
-               return PTR_ERR(blob);
-       blob_ptr = (void __user *)(unsigned long)out_resp->data;
-       if (copy_from_user(blob->data, blob_ptr, out_resp->length)) {
-               ret = -EFAULT;
-               goto out_blob;
-       }
-       /* Dropping the lock between create_blob and our access here is safe
-        * as only the same file_priv can remove the blob; at this point, it is
-        * not associated with any file_priv. */
-       mutex_lock(&dev->mode_config.blob_lock);
-       out_resp->blob_id = blob->base.id;
-       list_add_tail(&blob->head_file, &file_priv->blobs);
-       mutex_unlock(&dev->mode_config.blob_lock);
-       return 0;
- out_blob:
-       drm_property_unreference_blob(blob);
-       return ret;
- }
- /**
-  * drm_mode_destroyblob_ioctl - destroy a user blob property
-  * @dev: DRM device
-  * @data: ioctl data
-  * @file_priv: DRM file info
-  *
-  * Destroy an existing user-defined blob property.
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_destroyblob_ioctl(struct drm_device *dev,
-                              void *data, struct drm_file *file_priv)
- {
-       struct drm_mode_destroy_blob *out_resp = data;
-       struct drm_property_blob *blob = NULL, *bt;
-       bool found = false;
-       int ret = 0;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       blob = drm_property_lookup_blob(dev, out_resp->blob_id);
-       if (!blob)
-               return -ENOENT;
-       mutex_lock(&dev->mode_config.blob_lock);
-       /* Ensure the property was actually created by this user. */
-       list_for_each_entry(bt, &file_priv->blobs, head_file) {
-               if (bt == blob) {
-                       found = true;
-                       break;
-               }
-       }
-       if (!found) {
-               ret = -EPERM;
-               goto err;
-       }
-       /* We must drop head_file here, because we may not be the last
-        * reference on the blob. */
-       list_del_init(&blob->head_file);
-       mutex_unlock(&dev->mode_config.blob_lock);
-       /* One reference from lookup, and one from the filp. */
-       drm_property_unreference_blob(blob);
-       drm_property_unreference_blob(blob);
-       return 0;
- err:
-       mutex_unlock(&dev->mode_config.blob_lock);
-       drm_property_unreference_blob(blob);
-       return ret;
- }
- /* Some properties could refer to dynamic refcnt'd objects, or things that
-  * need special locking to handle lifetime issues (ie. to ensure the prop
-  * value doesn't become invalid part way through the property update due to
-  * race).  The value returned by reference via 'obj' should be passed back
-  * to drm_property_change_valid_put() after the property is set (and the
-  * object to which the property is attached has a chance to take it's own
-  * reference).
-  */
- bool drm_property_change_valid_get(struct drm_property *property,
-                                        uint64_t value, struct drm_mode_object **ref)
- {
-       int i;
-       if (property->flags & DRM_MODE_PROP_IMMUTABLE)
-               return false;
-       *ref = NULL;
-       if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
-               if (value < property->values[0] || value > property->values[1])
-                       return false;
-               return true;
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
-               int64_t svalue = U642I64(value);
-               if (svalue < U642I64(property->values[0]) ||
-                               svalue > U642I64(property->values[1]))
-                       return false;
-               return true;
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
-               uint64_t valid_mask = 0;
-               for (i = 0; i < property->num_values; i++)
-                       valid_mask |= (1ULL << property->values[i]);
-               return !(value & ~valid_mask);
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
-               struct drm_property_blob *blob;
-               if (value == 0)
-                       return true;
-               blob = drm_property_lookup_blob(property->dev, value);
-               if (blob) {
-                       *ref = &blob->base;
-                       return true;
-               } else {
-                       return false;
-               }
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-               /* a zero value for an object property translates to null: */
-               if (value == 0)
-                       return true;
-               *ref = __drm_mode_object_find(property->dev, value,
-                                             property->values[0]);
-               return *ref != NULL;
-       }
-       for (i = 0; i < property->num_values; i++)
-               if (property->values[i] == value)
-                       return true;
-       return false;
- }
- void drm_property_change_valid_put(struct drm_property *property,
-               struct drm_mode_object *ref)
- {
-       if (!ref)
-               return;
-       if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
-               drm_mode_object_unreference(ref);
-       } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB))
-               drm_property_unreference_blob(obj_to_blob(ref));
- }
- static 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;
+       return ret;
  }
  EXPORT_SYMBOL(drm_mode_plane_set_obj_prop);
  
- /**
-  * drm_mode_obj_get_properties_ioctl - get the current value of a object's property
-  * @dev: DRM device
-  * @data: ioctl data
-  * @file_priv: DRM file info
-  *
-  * This function retrieves the current value for an object's property. Compared
-  * to the connector specific ioctl this one is extended to also work on crtc and
-  * plane objects.
-  *
-  * Called by the user via ioctl.
-  *
-  * Returns:
-  * Zero on success, negative errno on failure.
-  */
- int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
-                                     struct drm_file *file_priv)
- {
-       struct drm_mode_obj_get_properties *arg = data;
-       struct drm_mode_object *obj;
-       int ret = 0;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       drm_modeset_lock_all(dev);
-       obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
-       if (!obj) {
-               ret = -ENOENT;
-               goto out;
-       }
-       if (!obj->properties) {
-               ret = -EINVAL;
-               goto out_unref;
-       }
-       ret = drm_mode_object_get_properties(obj, file_priv->atomic,
-                       (uint32_t __user *)(unsigned long)(arg->props_ptr),
-                       (uint64_t __user *)(unsigned long)(arg->prop_values_ptr),
-                       &arg->count_props);
- out_unref:
-       drm_mode_object_unreference(obj);
- out:
-       drm_modeset_unlock_all(dev);
-       return ret;
- }
- int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
-                                   struct drm_file *file_priv)
- {
-       struct drm_mode_obj_set_property *arg = data;
-       struct drm_mode_object *arg_obj;
-       struct drm_mode_object *prop_obj;
-       struct drm_property *property;
-       int i, ret = -EINVAL;
-       struct drm_mode_object *ref;
-       if (!drm_core_check_feature(dev, DRIVER_MODESET))
-               return -EINVAL;
-       drm_modeset_lock_all(dev);
-       arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
-       if (!arg_obj) {
-               ret = -ENOENT;
-               goto out;
-       }
-       if (!arg_obj->properties)
-               goto out_unref;
-       for (i = 0; i < arg_obj->properties->count; i++)
-               if (arg_obj->properties->properties[i]->base.id == arg->prop_id)
-                       break;
-       if (i == arg_obj->properties->count)
-               goto out_unref;
-       prop_obj = drm_mode_object_find(dev, arg->prop_id,
-                                       DRM_MODE_OBJECT_PROPERTY);
-       if (!prop_obj) {
-               ret = -ENOENT;
-               goto out_unref;
-       }
-       property = obj_to_property(prop_obj);
-       if (!drm_property_change_valid_get(property, arg->value, &ref))
-               goto out_unref;
-       switch (arg_obj->type) {
-       case DRM_MODE_OBJECT_CONNECTOR:
-               ret = drm_mode_connector_set_obj_prop(arg_obj, property,
-                                                     arg->value);
-               break;
-       case DRM_MODE_OBJECT_CRTC:
-               ret = drm_mode_crtc_set_obj_prop(arg_obj, property, arg->value);
-               break;
-       case DRM_MODE_OBJECT_PLANE:
-               ret = drm_mode_plane_set_obj_prop(obj_to_plane(arg_obj),
-                                                 property, arg->value);
-               break;
-       }
-       drm_property_change_valid_put(property, ref);
- out_unref:
-       drm_mode_object_unreference(arg_obj);
- out:
-       drm_modeset_unlock_all(dev);
-       return ret;
- }
  /**
   * drm_mode_crtc_set_gamma_size - set the gamma table size
   * @crtc: CRTC to set the gamma table size for
  int drm_mode_page_flip_ioctl(struct drm_device *dev,
                             void *data, struct drm_file *file_priv)
  {
 -      struct drm_mode_crtc_page_flip *page_flip = data;
 +      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 (page_flip->flags & ~DRM_MODE_PAGE_FLIP_FLAGS ||
 -          page_flip->reserved != 0)
 +      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)
        if (!crtc)
                return -ENOENT;
  
 +      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;
 +      }
 +
        drm_modeset_lock_crtc(crtc, crtc->primary);
        if (crtc->primary->fb == NULL) {
                /* The framebuffer is currently unbound, presumably
                goto out;
        }
  
 -      if (crtc->funcs->page_flip == NULL)
 -              goto out;
 -
        fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
        if (!fb) {
                ret = -ENOENT;
        }
  
        crtc->primary->old_fb = crtc->primary->fb;
 -      ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
 +      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);
        }
  
  out:
 +      if (ret)
 +              drm_crtc_vblank_put(crtc);
        if (fb)
                drm_framebuffer_unreference(fb);
        if (crtc->primary->old_fb)
index 12b7753a0d27b619f65663c6edb84fb0c38dd45c,630754684014a3a302a803c406b48fc3fc3a6029..b97c421c65f49e7f841fdfcba31c4498ee3067fd
@@@ -189,9 -189,8 +189,8 @@@ static int drm_getclient(struct drm_dev
         */
        if (client->idx == 0) {
                client->auth = file_priv->authenticated;
-               client->pid = pid_vnr(file_priv->pid);
-               client->uid = from_kuid_munged(current_user_ns(),
-                                              file_priv->uid);
+               client->pid = task_pid_vnr(current);
+               client->uid = overflowuid;
                client->magic = 0;
                client->iocs = 0;
  
@@@ -228,7 -227,6 +227,7 @@@ static int drm_getstats(struct drm_devi
  static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
  {
        struct drm_get_cap *req = data;
 +      struct drm_crtc *crtc;
  
        req->value = 0;
        switch (req->capability) {
        case DRM_CAP_ASYNC_PAGE_FLIP:
                req->value = dev->mode_config.async_page_flip;
                break;
 +      case DRM_CAP_PAGE_FLIP_TARGET:
 +              req->value = 1;
 +              drm_for_each_crtc(crtc, dev) {
 +                      if (!crtc->funcs->page_flip_target)
 +                              req->value = 0;
 +              }
 +              break;
        case DRM_CAP_CURSOR_WIDTH:
                if (dev->mode_config.cursor_width)
                        req->value = dev->mode_config.cursor_width;
index ba45d9d8bb62d5338b807dd43b56c4ba126c86b3,7ca8f347d79f62a025c73f37f3e382c9084d328f..60bcc48f84b9a667932e35b18c46d17d1bab3e49
@@@ -22,7 -22,6 +22,7 @@@
  #include "rockchip_drm_drv.h"
  #include "rockchip_drm_fb.h"
  #include "rockchip_drm_gem.h"
 +#include "rockchip_drm_psr.h"
  
  #define to_rockchip_fb(x) container_of(x, struct rockchip_drm_fb, fb)
  
@@@ -64,20 -63,9 +64,20 @@@ static int rockchip_drm_fb_create_handl
                                     rockchip_fb->obj[0], handle);
  }
  
 +static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
 +                               struct drm_file *file,
 +                               unsigned int flags, unsigned int color,
 +                               struct drm_clip_rect *clips,
 +                               unsigned int num_clips)
 +{
 +      rockchip_drm_psr_flush(fb->dev);
 +      return 0;
 +}
 +
  static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
        .destroy        = rockchip_drm_fb_destroy,
        .create_handle  = rockchip_drm_fb_create_handle,
 +      .dirty          = rockchip_drm_fb_dirty,
  };
  
  static struct rockchip_drm_fb *
@@@ -245,7 -233,8 +245,8 @@@ rockchip_atomic_commit_tail(struct drm_
  
        drm_atomic_helper_commit_modeset_enables(dev, state);
  
-       drm_atomic_helper_commit_planes(dev, state, true);
+       drm_atomic_helper_commit_planes(dev, state,
+                                       DRM_PLANE_COMMIT_ACTIVE_ONLY);
  
        drm_atomic_helper_commit_hw_done(state);
  
diff --combined include/drm/drm_crtc.h
index 7c8a77b181c2e0f14801eeba4a851877ca49ae77,3d33c90da9e5f3af503f0983a52d09405088893f..8ca71d66282b2f753e87ade53c3cf865313cc329
  #include <uapi/drm/drm_fourcc.h>
  #include <drm/drm_modeset_lock.h>
  #include <drm/drm_rect.h>
- #include <drm/drm_modeset.h>
+ #include <drm/drm_mode_object.h>
  #include <drm/drm_framebuffer.h>
  #include <drm/drm_modes.h>
  #include <drm/drm_connector.h>
+ #include <drm/drm_encoder.h>
+ #include <drm/drm_property.h>
  
  struct drm_device;
  struct drm_mode_set;
@@@ -81,33 -83,6 +83,6 @@@ struct drm_tile_group 
        u8 group_data[8];
  };
  
- struct drm_property_blob {
-       struct drm_mode_object base;
-       struct drm_device *dev;
-       struct list_head head_global;
-       struct list_head head_file;
-       size_t length;
-       unsigned char data[];
- };
- struct drm_property_enum {
-       uint64_t value;
-       struct list_head head;
-       char name[DRM_PROP_NAME_LEN];
- };
- struct drm_property {
-       struct list_head head;
-       struct drm_mode_object base;
-       uint32_t flags;
-       char name[DRM_PROP_NAME_LEN];
-       uint32_t num_values;
-       uint64_t *values;
-       struct drm_device *dev;
-       struct list_head enum_list;
- };
  struct drm_crtc;
  struct drm_encoder;
  struct drm_pending_vblank_event;
@@@ -390,24 -365,6 +365,24 @@@ struct drm_crtc_funcs 
                         struct drm_pending_vblank_event *event,
                         uint32_t flags);
  
 +      /**
 +       * @page_flip_target:
 +       *
 +       * Same as @page_flip but with an additional parameter specifying the
 +       * absolute target vertical blank period (as reported by
 +       * drm_crtc_vblank_count()) when the flip should take effect.
 +       *
 +       * Note that the core code calls drm_crtc_vblank_get before this entry
 +       * point, and will call drm_crtc_vblank_put if this entry point returns
 +       * any non-0 error code. It's the driver's responsibility to call
 +       * drm_crtc_vblank_put after this entry point returns 0, typically when
 +       * the flip completes.
 +       */
 +      int (*page_flip_target)(struct drm_crtc *crtc,
 +                              struct drm_framebuffer *fb,
 +                              struct drm_pending_vblank_event *event,
 +                              uint32_t flags, uint32_t target);
 +
        /**
         * @set_property:
         *
@@@ -679,97 -636,6 +654,6 @@@ struct drm_crtc 
        struct drm_modeset_acquire_ctx *acquire_ctx;
  };
  
- /**
-  * struct drm_encoder_funcs - encoder controls
-  *
-  * Encoders sit between CRTCs and connectors.
-  */
- struct drm_encoder_funcs {
-       /**
-        * @reset:
-        *
-        * Reset encoder 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.
-        */
-       void (*reset)(struct drm_encoder *encoder);
-       /**
-        * @destroy:
-        *
-        * Clean up encoder resources. This is only called at driver unload time
-        * through drm_mode_config_cleanup() since an encoder cannot be
-        * hotplugged in DRM.
-        */
-       void (*destroy)(struct drm_encoder *encoder);
-       /**
-        * @late_register:
-        *
-        * This optional hook can be used to register additional userspace
-        * interfaces attached to the encoder 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_encoder *encoder);
-       /**
-        * @early_unregister:
-        *
-        * This optional hook should be used to unregister the additional
-        * userspace interfaces attached to the encoder 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_encoder *encoder);
- };
- /**
-  * struct drm_encoder - central DRM encoder structure
-  * @dev: parent DRM device
-  * @head: list management
-  * @base: base KMS object
-  * @name: human readable name, can be overwritten by the driver
-  * @encoder_type: one of the DRM_MODE_ENCODER_<foo> types in drm_mode.h
-  * @possible_crtcs: bitmask of potential CRTC bindings
-  * @possible_clones: bitmask of potential sibling encoders for cloning
-  * @crtc: currently bound CRTC
-  * @bridge: bridge associated to the encoder
-  * @funcs: control functions
-  * @helper_private: mid-layer private data
-  *
-  * CRTCs drive pixels to encoders, which convert them into signals
-  * appropriate for a given connector or set of connectors.
-  */
- struct drm_encoder {
-       struct drm_device *dev;
-       struct list_head head;
-       struct drm_mode_object base;
-       char *name;
-       int encoder_type;
-       /**
-        * @index: Position inside the mode_config.list, can be used as an array
-        * index. It is invariant over the lifetime of the encoder.
-        */
-       unsigned index;
-       uint32_t possible_crtcs;
-       uint32_t possible_clones;
-       struct drm_crtc *crtc;
-       struct drm_bridge *bridge;
-       const struct drm_encoder_funcs *funcs;
-       const struct drm_encoder_helper_funcs *helper_private;
- };
  /**
   * struct drm_plane_state - mutable plane state
   * @plane: backpointer to the plane
@@@ -1136,11 -1002,32 +1020,32 @@@ struct drm_plane 
  
  /**
   * struct drm_bridge_funcs - drm_bridge control functions
-  * @attach: Called during drm_bridge_attach
   */
  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 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
@@@ -2109,18 -1998,11 +2016,11 @@@ struct drm_mode_config 
                for_each_if ((encoder_mask) & (1 << drm_encoder_index(encoder)))
  
  #define obj_to_crtc(x) container_of(x, struct drm_crtc, base)
- #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
  #define obj_to_mode(x) container_of(x, struct drm_display_mode, base)
  #define obj_to_fb(x) container_of(x, struct drm_framebuffer, base)
- #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)
  #define obj_to_plane(x) container_of(x, struct drm_plane, base)
  
- struct drm_prop_enum_list {
-       int type;
-       char *name;
- };
  extern __printf(6, 7)
  int drm_crtc_init_with_planes(struct drm_device *dev,
                              struct drm_crtc *crtc,
@@@ -2154,37 -2036,6 +2054,6 @@@ static inline uint32_t drm_crtc_mask(st
        return 1 << drm_crtc_index(crtc);
  }
  
- extern __printf(5, 6)
- int drm_encoder_init(struct drm_device *dev,
-                    struct drm_encoder *encoder,
-                    const struct drm_encoder_funcs *funcs,
-                    int encoder_type, const char *name, ...);
- /**
-  * drm_encoder_index - find the index of a registered encoder
-  * @encoder: encoder to find index for
-  *
-  * Given a registered encoder, return the index of that encoder within a DRM
-  * device's list of encoders.
-  */
- static inline unsigned int drm_encoder_index(struct drm_encoder *encoder)
- {
-       return encoder->index;
- }
- /**
-  * drm_encoder_crtc_ok - can a given crtc drive a given encoder?
-  * @encoder: encoder to test
-  * @crtc: crtc to test
-  *
-  * Return false if @encoder can't be driven by @crtc, true otherwise.
-  */
- static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
-                                      struct drm_crtc *crtc)
- {
-       return !!(encoder->possible_crtcs & drm_crtc_mask(crtc));
- }
  extern __printf(8, 9)
  int drm_universal_plane_init(struct drm_device *dev,
                             struct drm_plane *plane,
@@@ -2220,75 -2071,15 +2089,15 @@@ extern void drm_crtc_get_hv_timing(cons
  extern int drm_crtc_force_disable(struct drm_crtc *crtc);
  extern int drm_crtc_force_disable_all(struct drm_device *dev);
  
- extern void drm_encoder_cleanup(struct drm_encoder *encoder);
  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);
  
- static inline bool drm_property_type_is(struct drm_property *property,
-               uint32_t type)
- {
-       /* instanceof for props.. handles extended type vs original types: */
-       if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
-               return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
-       return property->flags & type;
- }
- extern int drm_object_property_set_value(struct drm_mode_object *obj,
-                                        struct drm_property *property,
-                                        uint64_t val);
- extern int drm_object_property_get_value(struct drm_mode_object *obj,
-                                        struct drm_property *property,
-                                        uint64_t *value);
- extern void drm_object_attach_property(struct drm_mode_object *obj,
-                                      struct drm_property *property,
-                                      uint64_t init_val);
- extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
-                                               const char *name, int num_values);
- extern struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
-                                        const char *name,
-                                        const struct drm_prop_enum_list *props,
-                                        int num_values);
- struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
-                                        int flags, const char *name,
-                                        const struct drm_prop_enum_list *props,
-                                        int num_props,
-                                        uint64_t supported_bits);
- struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
-                                        const char *name,
-                                        uint64_t min, uint64_t max);
- struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
-                                        int flags, const char *name,
-                                        int64_t min, int64_t max);
- struct drm_property *drm_property_create_object(struct drm_device *dev,
-                                        int flags, const char *name, uint32_t type);
- struct drm_property *drm_property_create_bool(struct drm_device *dev, int flags,
-                                        const char *name);
- struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
-                                                    size_t length,
-                                                    const void *data);
- struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
-                                                    uint32_t id);
- int drm_property_replace_global_blob(struct drm_device *dev,
-                                    struct drm_property_blob **replace,
-                                    size_t length,
-                                    const void *data,
-                                    struct drm_mode_object *obj_holds_id,
-                                    struct drm_property *prop_holds_id);
- struct drm_property_blob *drm_property_reference_blob(struct drm_property_blob *blob);
- void drm_property_unreference_blob(struct drm_property_blob *blob);
- extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
- extern int drm_property_add_enum(struct drm_property *property, int index,
-                                uint64_t value, const char *name);
  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 uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth);
  extern struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
                                                         char topology[8]);
  extern struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
@@@ -2333,22 -2124,6 +2142,6 @@@ static inline struct drm_crtc *drm_crtc
        return mo ? obj_to_crtc(mo) : NULL;
  }
  
- static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
-       uint32_t id)
- {
-       struct drm_mode_object *mo;
-       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
-       return mo ? obj_to_encoder(mo) : NULL;
- }
- static inline struct drm_property *drm_property_find(struct drm_device *dev,
-               uint32_t id)
- {
-       struct drm_mode_object *mo;
-       mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
-       return mo ? obj_to_property(mo) : NULL;
- }
  /*
   * Extract a degamma/gamma LUT value provided by user and round it to the
   * precision supported by the hardware.
@@@ -2444,6 -2219,7 +2237,7 @@@ extern int drm_bridge_add(struct drm_br
  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,