From: Ville Syrj?l? <ville.syrj...@linux.intel.com>

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 at linux.intel.com>
---
 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

Reply via email to