@@ -123,6 +123,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,
+ struct drm_atomic_state *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) \
@@ -755,6 +763,7 @@ int drm_crtc_init_with_planes(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++;
@@ -859,6 +868,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;
@@ -1077,6 +1087,7 @@ int drm_universal_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,
@@ -1894,7 +1905,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;
@@ -3418,7 +3429,7 @@ 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);
@@ -3437,13 +3448,27 @@ EXPORT_SYMBOL(drm_object_attach_property);
* 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)
+ 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;
}
}
@@ -3473,7 +3498,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;
}
}
@@ -3694,27 +3719,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;
}
@@ -3806,7 +3839,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;
}
@@ -3820,7 +3855,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;
}
@@ -3835,7 +3871,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;
}
@@ -3951,7 +3988,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;
@@ -451,7 +451,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);
@@ -1655,7 +1655,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;
@@ -184,7 +184,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) ||
@@ -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);
@@ -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);
@@ -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);
@@ -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;
@@ -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;
@@ -9494,8 +9494,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;
@@ -3281,7 +3281,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;
@@ -1055,7 +1055,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;
@@ -2064,7 +2064,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;
@@ -2141,7 +2142,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;
@@ -2153,7 +2156,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;
@@ -2165,7 +2170,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;
@@ -2177,7 +2184,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;
@@ -1297,7 +1297,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);
}
/**
@@ -1455,7 +1456,8 @@ intel_tv_set_property(struct drm_connector *connector,
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;
@@ -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;
@@ -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);
}
}
@@ -579,12 +579,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);
}
}
@@ -111,7 +111,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)
@@ -76,7 +76,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)
@@ -741,8 +741,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;
@@ -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];
};
@@ -361,6 +366,7 @@ struct drm_crtc {
void *helper_private;
struct drm_object_properties properties;
+ struct drm_object_property_values propvals;
};
@@ -520,6 +526,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_* */
@@ -603,6 +610,7 @@ struct drm_plane {
const struct drm_plane_funcs *funcs;
struct drm_object_properties properties;
+ struct drm_object_property_values propvals;
enum drm_plane_type type;
};
@@ -969,8 +977,9 @@ static inline bool drm_property_type_valid(struct drm_property *property)
}
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);
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. Signed-off-by: Rob Clark <robdclark@gmail.com> --- 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(-)