From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Add a new blob property MODE_IDS to connectors. This property contains a list a mode object IDs attached to the connector (either probed modes, or user attached modes). Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/gpu/drm/drm_crtc.c | 77 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc_helper.c | 1 + include/drm/drm_crtc.h | 2 + 3 files changed, 80 insertions(+), 0 deletions(-) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 958a4b0..cfef9de 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -508,6 +508,9 @@ int drm_connector_init(struct drm_device *dev, drm_connector_attach_property(connector, dev->mode_config.dpms_property, 0); + drm_connector_attach_property(connector, + dev->mode_config.mode_ids_property, 0); + out: mutex_unlock(&dev->mode_config.mutex); @@ -713,6 +716,7 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) { struct drm_property *edid; struct drm_property *dpms; + struct drm_property *mode_ids; /* * Standard properties (apply to all connectors) @@ -727,6 +731,11 @@ static int drm_mode_create_standard_connector_properties(struct drm_device *dev) ARRAY_SIZE(drm_dpms_enum_list)); dev->mode_config.dpms_property = dpms; + mode_ids = drm_property_create(dev, DRM_MODE_PROP_BLOB | + DRM_MODE_PROP_IMMUTABLE, + "MODE_IDS", 0); + dev->mode_config.mode_ids_property = mode_ids; + return 0; } @@ -2648,6 +2657,10 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, } drm_mode_attachmode(dev, connector, mode); + + ret = drm_mode_connector_update_mode_ids_property(connector); + if (ret) + drm_mode_remove(connector, mode); out: mutex_unlock(&dev->mode_config.mutex); return ret; @@ -3144,6 +3157,70 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_mode_connector_update_edid_property); +int drm_mode_connector_update_mode_ids_property(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property_blob *blob = NULL; + struct drm_property_blob *old_blob = NULL; + struct drm_display_mode *mode; + uint64_t value; + int i = 0; + int ret; + + ret = drm_connector_property_get_value(connector, + dev->mode_config.mode_ids_property, + &value); + if (ret) + return ret; + + if (value) { + struct drm_mode_object *obj = drm_mode_object_find(dev, value, DRM_MODE_OBJECT_BLOB); + if (!obj) + return -ENOENT; + + old_blob = obj_to_blob(obj); + } + + list_for_each_entry(mode, &connector->modes, head) + i++; + list_for_each_entry(mode, &connector->user_modes, head) + i++; + + if (i) { + uint32_t *mode_ids = kcalloc(i, sizeof mode_ids[0], GFP_KERNEL); + if (!mode_ids) + return -ENOMEM; + + i = 0; + list_for_each_entry(mode, &connector->modes, head) + mode_ids[i++] = mode->base.id; + list_for_each_entry(mode, &connector->user_modes, head) + mode_ids[i++] = mode->base.id; + + blob = drm_property_create_blob(dev, i * sizeof mode_ids[0], mode_ids); + + kfree(mode_ids); + + if (!blob) + return -ENOMEM; + } + + ret = drm_connector_property_set_value(connector, + dev->mode_config.mode_ids_property, + blob ? blob->base.id : 0); + if (ret) { + if (blob) + drm_property_destroy_blob(dev, blob); + return ret; + } + + if (old_blob) + drm_property_destroy_blob(dev, old_blob); + + return ret; +} +EXPORT_SYMBOL(drm_mode_connector_update_mode_ids_property); + static bool range_property_is_signed(const struct drm_property *property) { return property->values[0] > property->values[1]; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index ebbfcc6..bc24c0e 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -131,6 +131,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector, goto prune; drm_mode_connector_list_update(connector); + drm_mode_connector_update_mode_ids_property(connector); if (maxX && maxY) drm_mode_validate_size(dev, &connector->modes, maxX, diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 99bd489..c8bfdf1 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -790,6 +790,7 @@ struct drm_mode_config { struct list_head property_blob_list; struct drm_property *edid_property; struct drm_property *dpms_property; + struct drm_property *mode_ids_property; /* DVI-I properties */ struct drm_property *dvi_i_subconnector_property; @@ -910,6 +911,7 @@ extern void drm_mode_set_crtcinfo(struct drm_display_mode *p, 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_mode_connector_update_mode_ids_property(struct drm_connector *connector); extern int drm_connector_property_set_value(struct drm_connector *connector, struct drm_property *property, uint64_t value); -- 1.7.3.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel