diff mbox

[RFCv3,07/14] drm: split propvals out and blob property support

Message ID 1384980493-25499-8-git-send-email-robdclark@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Rob Clark Nov. 20, 2013, 8:48 p.m. UTC
Split property values out into a different struct, so we can later
move property values into state structs.  This will allow the
property values to stay in sync w/ the state updates which are
either discarded or atomically committed.

And since we are touching all the same code, add support for mutable
blob properties, which will also be needed for atomic modeset.
---
 drivers/gpu/drm/drm_crtc.c                  | 79 +++++++++++++++++++++--------
 drivers/gpu/drm/drm_fb_helper.c             |  3 +-
 drivers/gpu/drm/gma500/cdv_intel_dp.c       |  3 +-
 drivers/gpu/drm/gma500/cdv_intel_hdmi.c     |  3 +-
 drivers/gpu/drm/gma500/cdv_intel_lvds.c     |  6 ++-
 drivers/gpu/drm/gma500/mdfld_dsi_output.c   |  8 +--
 drivers/gpu/drm/gma500/psb_intel_lvds.c     |  6 ++-
 drivers/gpu/drm/gma500/psb_intel_sdvo.c     | 19 +++++--
 drivers/gpu/drm/i2c/ch7006_drv.c            |  4 +-
 drivers/gpu/drm/i915/intel_display.c        |  3 +-
 drivers/gpu/drm/i915/intel_dp.c             |  3 +-
 drivers/gpu/drm/i915/intel_hdmi.c           |  3 +-
 drivers/gpu/drm/i915/intel_sdvo.c           | 19 +++++--
 drivers/gpu/drm/i915/intel_tv.c             |  6 ++-
 drivers/gpu/drm/nouveau/dispnv04/tvnv17.c   |  3 +-
 drivers/gpu/drm/nouveau/nouveau_connector.c |  4 +-
 drivers/gpu/drm/omapdrm/omap_drv.c          |  6 ++-
 drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c   |  3 +-
 drivers/gpu/drm/rcar-du/rcar_du_vgacon.c    |  3 +-
 drivers/gpu/drm/shmobile/shmob_drm_crtc.c   |  4 +-
 include/drm/drm_crtc.h                      | 11 +++-
 21 files changed, 142 insertions(+), 57 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 61ce72d..b81baae 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -90,6 +90,14 @@  void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
 
+static int drm_mode_set_obj_prop(struct drm_mode_object *obj,
+		void *state, struct drm_property *property,
+		uint64_t value, void *blob_data);
+static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev,
+		int length, void *data);
+static void drm_property_destroy_blob(struct drm_device *dev,
+		struct drm_property_blob *blob);
+
 /* Avoid boilerplate.  I'm tired of typing. */
 #define DRM_ENUM_NAME_FN(fnname, list)				\
 	const char *fnname(int val)				\
@@ -644,6 +652,7 @@  int drm_crtc_init(struct drm_device *dev, struct drm_crtc *crtc,
 		goto out;
 
 	crtc->base.properties = &crtc->properties;
+	crtc->base.propvals = &crtc->propvals;
 
 	list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
 	dev->mode_config.num_crtc++;
@@ -733,6 +742,7 @@  int drm_connector_init(struct drm_device *dev,
 		goto out;
 
 	connector->base.properties = &connector->properties;
+	connector->base.propvals = &connector->propvals;
 	connector->dev = dev;
 	connector->funcs = funcs;
 	connector->connector_type = connector_type;
@@ -906,6 +916,7 @@  int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
 		goto out;
 
 	plane->base.properties = &plane->properties;
+	plane->base.propvals = &plane->propvals;
 	plane->dev = dev;
 	plane->funcs = funcs;
 	plane->format_types = kmalloc(sizeof(uint32_t) * format_count,
@@ -1712,7 +1723,7 @@  int drm_mode_getconnector(struct drm_device *dev, void *data,
 				goto out;
 			}
 
-			if (put_user(connector->properties.values[i],
+			if (put_user(connector->propvals.values[i],
 				     prop_values + copied)) {
 				ret = -EFAULT;
 				goto out;
@@ -3021,19 +3032,33 @@  void drm_object_attach_property(struct drm_mode_object *obj,
 	}
 
 	obj->properties->ids[count] = property->base.id;
-	obj->properties->values[count] = init_val;
+	obj->propvals->values[count] = init_val;
 	obj->properties->count++;
 }
 EXPORT_SYMBOL(drm_object_attach_property);
 
 int drm_object_property_set_value(struct drm_mode_object *obj,
-				  struct drm_property *property, uint64_t val)
+				  struct drm_object_property_values *propvals,
+				  struct drm_property *property, uint64_t val,
+				  void *blob_data)
 {
 	int i;
 
 	for (i = 0; i < obj->properties->count; i++) {
 		if (obj->properties->ids[i] == property->base.id) {
-			obj->properties->values[i] = val;
+			struct drm_device *dev = property->dev;
+			if (property->flags & DRM_MODE_PROP_BLOB) {
+				struct drm_property_blob *blob, *old_blob = NULL;
+				old_blob = drm_property_blob_find(dev, propvals->values[i]);
+				blob = drm_property_create_blob(dev, val, blob_data);
+				if (!blob)
+					return -ENOMEM;
+				propvals->values[i] = blob->base.id;
+				if (old_blob)
+					drm_property_destroy_blob(dev, old_blob);
+			} else {
+				propvals->values[i] = val;
+			}
 			return 0;
 		}
 	}
@@ -3049,7 +3074,7 @@  int drm_object_property_get_value(struct drm_mode_object *obj,
 
 	for (i = 0; i < obj->properties->count; i++) {
 		if (obj->properties->ids[i] == property->base.id) {
-			*val = obj->properties->values[i];
+			*val = obj->propvals->values[i];
 			return 0;
 		}
 	}
@@ -3234,27 +3259,35 @@  int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 					    struct edid *edid)
 {
 	struct drm_device *dev = connector->dev;
-	int ret, size;
+	struct drm_mode_object *obj = &connector->base;
+	struct drm_property *edid_prop = dev->mode_config.edid_property;
+	int i, ret, size;
 
-	if (connector->edid_blob_ptr)
-		drm_property_destroy_blob(dev, connector->edid_blob_ptr);
+	/* property_blob will be recreated by drm_object_property_set_value(): */
+	connector->edid_blob_ptr = NULL;
 
 	/* Delete edid, when there is none. */
 	if (!edid) {
-		connector->edid_blob_ptr = NULL;
-		ret = drm_object_property_set_value(&connector->base, dev->mode_config.edid_property, 0);
+		ret = drm_object_property_set_value(obj,
+				&connector->propvals, edid_prop, 0, NULL);
 		return ret;
 	}
 
 	size = EDID_LENGTH * (1 + edid->extensions);
-	connector->edid_blob_ptr = drm_property_create_blob(connector->dev,
-							    size, edid);
-	if (!connector->edid_blob_ptr)
-		return -EINVAL;
 
-	ret = drm_object_property_set_value(&connector->base,
-					       dev->mode_config.edid_property,
-					       connector->edid_blob_ptr->base.id);
+	ret = drm_object_property_set_value(obj,
+			&connector->propvals, edid_prop, size, edid);
+	if (ret)
+		return ret;
+
+	/* find the blob object created for us by drm_object_property_set_value(): */
+	for (i = 0; i < obj->properties->count; i++) {
+		if (obj->properties->ids[i] == edid_prop->base.id) {
+			connector->edid_blob_ptr = drm_property_blob_find(dev,
+					connector->propvals.values[i]);
+			break;
+		}
+	}
 
 	return ret;
 }
@@ -3332,7 +3365,9 @@  static int drm_mode_connector_set_obj_prop(struct drm_connector *connector,
 
 	/* store the property value if successful */
 	if (!ret)
-		drm_object_property_set_value(&connector->base, property, value);
+		drm_object_property_set_value(&connector->base,
+				&connector->propvals, property, value, blob_data);
+
 	return ret;
 }
 
@@ -3346,7 +3381,8 @@  static int drm_mode_crtc_set_obj_prop(struct drm_crtc *crtc,
 		ret = crtc->funcs->set_property(crtc, state, property,
 				value, blob_data);
 	if (!ret)
-		drm_object_property_set_value(&crtc->base, property, value);
+		drm_object_property_set_value(&crtc->base, &crtc->propvals,
+				property, value, NULL);
 
 	return ret;
 }
@@ -3361,7 +3397,8 @@  static int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
 		ret = plane->funcs->set_property(plane, state, property,
 				value, blob_data);
 	if (!ret)
-		drm_object_property_set_value(&plane->base, property, value);
+		drm_object_property_set_value(&plane->base, &plane->propvals,
+				property, value, NULL);
 
 	return ret;
 }
@@ -3464,7 +3501,7 @@  int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
 				ret = -EFAULT;
 				goto out;
 			}
-			if (put_user(obj->properties->values[i],
+			if (put_user(obj->propvals->values[i],
 				     prop_values_ptr + copied)) {
 				ret = -EFAULT;
 				goto out;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a19401..1b6b6f4 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -431,7 +431,8 @@  static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode)
 			connector = fb_helper->connector_info[j]->connector;
 			connector->funcs->dpms(connector, dpms_mode);
 			drm_object_property_set_value(&connector->base,
-				dev->mode_config.dpms_property, dpms_mode);
+				&connector->propvals,
+				dev->mode_config.dpms_property, dpms_mode, NULL);
 		}
 	}
 	drm_modeset_unlock_all(dev);
diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c
index 523dfc9..f2fd091 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_dp.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c
@@ -1654,7 +1654,8 @@  cdv_intel_dp_set_property(struct drm_connector *connector,
 	struct cdv_intel_dp *intel_dp = encoder->dev_priv;
 	int ret;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			&connector->propvals, property, val, blob_data);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
index 74e5de1..188444a 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c
@@ -191,7 +191,8 @@  static int cdv_hdmi_set_property(struct drm_connector *connector,
 			return 0;
 
 		if (drm_object_property_set_value(&connector->base,
-							property, value))
+							&connector->propvals,
+							property, value, blob_data))
 			return -1;
 
 		centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
index 97d76c1..2dcdd01 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -486,8 +486,9 @@  static int cdv_intel_lvds_set_property(struct drm_connector *connector,
 			return 0;
 
 		if (drm_object_property_set_value(&connector->base,
+							&connector->propvals,
 							property,
-							value))
+							value, blob_data))
 			return -1;
 
 		if (crtc->saved_mode.hdisplay != 0 &&
@@ -501,8 +502,9 @@  static int cdv_intel_lvds_set_property(struct drm_connector *connector,
 		}
 	} else if (!strcmp(property->name, "backlight") && encoder) {
 		if (drm_object_property_set_value(&connector->base,
+							&connector->propvals,
 							property,
-							value))
+							value, blob_data))
 			return -1;
 		else
                         gma_backlight_set(encoder->dev, value);
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
index 76dadee..f29461a 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -276,7 +276,8 @@  static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
 			goto set_prop_done;
 
 		if (drm_object_property_set_value(&connector->base,
-							property, value))
+							&connector->propvals,
+							property, value, blob_data))
 			goto set_prop_error;
 
 		centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
@@ -300,8 +301,9 @@  static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
 			}
 		}
 	} else if (!strcmp(property->name, "backlight") && encoder) {
-		if (drm_object_property_set_value(&connector->base, property,
-									value))
+		if (drm_object_property_set_value(&connector->base,
+							&connector->propvals,
+							property, value, blob_data))
 			goto set_prop_error;
 		else
 			gma_backlight_set(encoder->dev, value);
diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c
index e3a3923..090a6b3 100644
--- a/drivers/gpu/drm/gma500/psb_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c
@@ -606,8 +606,9 @@  int psb_intel_lvds_set_property(struct drm_connector *connector,
 			goto set_prop_done;
 
 		if (drm_object_property_set_value(&connector->base,
+							&connector->propvals,
 							property,
-							value))
+							value, blob_data))
 			goto set_prop_error;
 
 		if (crtc->saved_mode.hdisplay != 0 &&
@@ -621,8 +622,9 @@  int psb_intel_lvds_set_property(struct drm_connector *connector,
 		}
 	} else if (!strcmp(property->name, "backlight")) {
 		if (drm_object_property_set_value(&connector->base,
+							&connector->propvals,
 							property,
-							value))
+							value, blob_data))
 			goto set_prop_error;
 		else
                         gma_backlight_set(encoder->dev, value);
diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
index 5ff83dc..0e50506 100644
--- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c
+++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c
@@ -1717,7 +1717,8 @@  psb_intel_sdvo_set_property(struct drm_connector *connector,
 	uint8_t cmd;
 	int ret;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			&connector->propvals, property, val, blob_data);
 	if (ret)
 		return ret;
 
@@ -1773,7 +1774,9 @@  psb_intel_sdvo_set_property(struct drm_connector *connector,
 		temp_value = val;
 		if (psb_intel_sdvo_connector->left == property) {
 			drm_object_property_set_value(&connector->base,
-							 psb_intel_sdvo_connector->right, val);
+							 &connector->propvals,
+							 psb_intel_sdvo_connector->right,
+							 val, blob_data);
 			if (psb_intel_sdvo_connector->left_margin == temp_value)
 				return 0;
 
@@ -1785,7 +1788,9 @@  psb_intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (psb_intel_sdvo_connector->right == property) {
 			drm_object_property_set_value(&connector->base,
-							 psb_intel_sdvo_connector->left, val);
+							 &connector->propvals,
+							 psb_intel_sdvo_connector->left,
+							 val, blob_data);
 			if (psb_intel_sdvo_connector->right_margin == temp_value)
 				return 0;
 
@@ -1797,7 +1802,9 @@  psb_intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (psb_intel_sdvo_connector->top == property) {
 			drm_object_property_set_value(&connector->base,
-							 psb_intel_sdvo_connector->bottom, val);
+							 &connector->propvals,
+							 psb_intel_sdvo_connector->bottom,
+							 val, blob_data);
 			if (psb_intel_sdvo_connector->top_margin == temp_value)
 				return 0;
 
@@ -1809,7 +1816,9 @@  psb_intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (psb_intel_sdvo_connector->bottom == property) {
 			drm_object_property_set_value(&connector->base,
-							 psb_intel_sdvo_connector->top, val);
+							 &connector->propvals,
+							 psb_intel_sdvo_connector->top,
+							 val, blob_data);
 			if (psb_intel_sdvo_connector->bottom_margin == temp_value)
 				return 0;
 
diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c
index 51fa323..a89c205 100644
--- a/drivers/gpu/drm/i2c/ch7006_drv.c
+++ b/drivers/gpu/drm/i2c/ch7006_drv.c
@@ -214,9 +214,9 @@  static enum drm_connector_status ch7006_encoder_detect(struct drm_encoder *encod
 	else
 		priv->subconnector = DRM_MODE_SUBCONNECTOR_Unknown;
 
-	drm_object_property_set_value(&connector->base,
+	drm_object_property_set_value(&connector->base, &connector->propvals,
 			encoder->dev->mode_config.tv_subconnector_property,
-							priv->subconnector);
+			priv->subconnector, NULL);
 
 	return priv->subconnector ? connector_status_connected :
 					connector_status_disconnected;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 741188f..3b4e60e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8959,8 +8959,9 @@  intel_modeset_update_state(struct drm_device *dev, unsigned prepare_pipes)
 
 			connector->dpms = DRM_MODE_DPMS_ON;
 			drm_object_property_set_value(&connector->base,
+							 &connector->propvals,
 							 dpms_property,
-							 DRM_MODE_DPMS_ON);
+							 DRM_MODE_DPMS_ON, NULL);
 
 			intel_encoder = to_intel_encoder(connector->encoder);
 			intel_encoder->connectors_active = true;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c9b3e56..7d9d79a 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3171,7 +3171,8 @@  intel_dp_set_property(struct drm_connector *connector,
 	struct intel_dp *intel_dp = enc_to_intel_dp(&intel_encoder->base);
 	int ret;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			&connector->propvals, property, val, blob_data);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 59b1212..566c71b 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1015,7 +1015,8 @@  intel_hdmi_set_property(struct drm_connector *connector,
 	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			&connector->propvals, property, val, blob_data);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 9f805df..1a334b0 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -2044,7 +2044,8 @@  intel_sdvo_set_property(struct drm_connector *connector,
 	uint8_t cmd;
 	int ret;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			&connector->propvals, property, val, blob_data);
 	if (ret)
 		return ret;
 
@@ -2121,7 +2122,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 		temp_value = val;
 		if (intel_sdvo_connector->left == property) {
 			drm_object_property_set_value(&connector->base,
-							 intel_sdvo_connector->right, val);
+							 &connector->propvals,
+							 intel_sdvo_connector->right,
+							 val, blob_data);
 			if (intel_sdvo_connector->left_margin == temp_value)
 				return 0;
 
@@ -2133,7 +2136,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (intel_sdvo_connector->right == property) {
 			drm_object_property_set_value(&connector->base,
-							 intel_sdvo_connector->left, val);
+							 &connector->propvals,
+							 intel_sdvo_connector->left,
+							 val, blob_data);
 			if (intel_sdvo_connector->right_margin == temp_value)
 				return 0;
 
@@ -2145,7 +2150,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (intel_sdvo_connector->top == property) {
 			drm_object_property_set_value(&connector->base,
-							 intel_sdvo_connector->bottom, val);
+							 &connector->propvals,
+							 intel_sdvo_connector->bottom,
+							 val, blob_data);
 			if (intel_sdvo_connector->top_margin == temp_value)
 				return 0;
 
@@ -2157,7 +2164,9 @@  intel_sdvo_set_property(struct drm_connector *connector,
 			goto set_value;
 		} else if (intel_sdvo_connector->bottom == property) {
 			drm_object_property_set_value(&connector->base,
-							 intel_sdvo_connector->top, val);
+							 &connector->propvals,
+							 intel_sdvo_connector->top,
+							 val, blob_data);
 			if (intel_sdvo_connector->bottom_margin == temp_value)
 				return 0;
 
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 5fa6839..821bd05 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1292,7 +1292,8 @@  static void intel_tv_find_better_format(struct drm_connector *connector)
 
 	intel_tv->tv_format = tv_mode->name;
 	drm_object_property_set_value(&connector->base,
-		connector->dev->mode_config.tv_mode_property, i);
+		&connector->propvals,
+		connector->dev->mode_config.tv_mode_property, i, NULL);
 }
 
 /**
@@ -1449,7 +1450,8 @@  intel_tv_set_property(struct drm_connector *connector, void *state,
 	int ret = 0;
 	bool changed = false;
 
-	ret = drm_object_property_set_value(&connector->base, property, val);
+	ret = drm_object_property_set_value(&connector->base,
+			 &connector->propvals, property, val, blob_data);
 	if (ret < 0)
 		goto out;
 
diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
index acef48f..64c60fcb 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c
@@ -196,8 +196,9 @@  nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 	}
 
 	drm_object_property_set_value(&connector->base,
+					 &connector->propvals,
 					 conf->tv_subconnector_property,
-					 tv_enc->subconnector);
+					 tv_enc->subconnector, NULL);
 
 	if (!reliable) {
 		return connector_status_unknown;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 36499e1..7390f7a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -227,10 +227,12 @@  nouveau_connector_set_encoder(struct drm_connector *connector,
 
 	if (nv_connector->type == DCB_CONNECTOR_DVI_I) {
 		drm_object_property_set_value(&connector->base,
+			&connector->propvals,
 			dev->mode_config.dvi_i_subconnector_property,
 			nv_encoder->dcb->type == DCB_OUTPUT_TMDS ?
 			DRM_MODE_SUBCONNECTOR_DVID :
-			DRM_MODE_SUBCONNECTOR_DVIA);
+			DRM_MODE_SUBCONNECTOR_DVIA,
+			NULL);
 	}
 }
 
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index bb07519..1b09696 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -553,12 +553,14 @@  static void dev_lastclose(struct drm_device *dev)
 		 */
 		for (i = 0; i < priv->num_crtcs; i++) {
 			drm_object_property_set_value(&priv->crtcs[i]->base,
-					priv->rotation_prop, 0);
+					&priv->crtcs[i]->propvals,
+					priv->rotation_prop, 0, NULL);
 		}
 
 		for (i = 0; i < priv->num_planes; i++) {
 			drm_object_property_set_value(&priv->planes[i]->base,
-					priv->rotation_prop, 0);
+					&priv->planes[i]->propvals,
+					priv->rotation_prop, 0, NULL);
 		}
 	}
 
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 4f3ba93..708e044 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -118,7 +118,8 @@  int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
 
 	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
 	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+		&connector->propvals,
+		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF, NULL);
 
 	ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index 41d563a..da16774 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -83,7 +83,8 @@  int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
 
 	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
 	drm_object_property_set_value(&connector->base,
-		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+		&connector->propvals,
+		rcdu->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF, NULL);
 
 	ret = drm_mode_connector_attach_encoder(connector, &renc->encoder);
 	if (ret < 0)
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 562f9a4..b72ba99 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -738,8 +738,8 @@  int shmob_drm_connector_create(struct shmob_drm_device *sdev,
 	connector->encoder = encoder;
 
 	drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
-	drm_object_property_set_value(&connector->base,
-		sdev->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF);
+	drm_object_property_set_value(&connector->base, &connector->propvals,
+		sdev->ddev->mode_config.dpms_property, DRM_MODE_DPMS_OFF, NULL);
 
 	return 0;
 
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index d3abc9c..a18d240 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -41,6 +41,7 @@  struct drm_framebuffer;
 struct drm_object_properties;
 struct drm_file;
 struct drm_clip_rect;
+struct drm_object_property_values;
 
 #define DRM_MODE_OBJECT_CRTC 0xcccccccc
 #define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
@@ -56,12 +57,16 @@  struct drm_mode_object {
 	uint32_t id;
 	uint32_t type;
 	struct drm_object_properties *properties;
+	struct drm_object_property_values *propvals;
 };
 
 #define DRM_OBJECT_MAX_PROPERTY 24
 struct drm_object_properties {
 	int count;
 	uint32_t ids[DRM_OBJECT_MAX_PROPERTY];
+};
+
+struct drm_object_property_values {
 	uint64_t values[DRM_OBJECT_MAX_PROPERTY];
 };
 
@@ -465,6 +470,7 @@  struct drm_crtc {
 	void *helper_private;
 
 	struct drm_object_properties properties;
+	struct drm_object_property_values propvals;
 };
 
 
@@ -630,6 +636,7 @@  struct drm_connector {
 
 	struct drm_property_blob *edid_blob_ptr;
 	struct drm_object_properties properties;
+	struct drm_object_property_values propvals;
 
 	uint8_t polled; /* DRM_CONNECTOR_POLL_* */
 
@@ -705,6 +712,7 @@  struct drm_plane {
 	const struct drm_plane_funcs *funcs;
 
 	struct drm_object_properties properties;
+	struct drm_object_property_values propvals;
 };
 
 /**
@@ -1019,8 +1027,9 @@  extern void drm_mode_connector_list_update(struct drm_connector *connector);
 extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
 						struct edid *edid);
 extern int drm_object_property_set_value(struct drm_mode_object *obj,
+					 struct drm_object_property_values *propvals,
 					 struct drm_property *property,
-					 uint64_t val);
+					 uint64_t val, void *blob_data);
 extern int drm_object_property_get_value(struct drm_mode_object *obj,
 					 struct drm_property *property,
 					 uint64_t *value);