Merge tag 'drm-misc-next-2017-05-16' of git://anongit.freedesktop.org/git/drm-misc...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / drm_connector.c
index 9f847615ac74ab012f6203a141627a5c6f5993e2..5cd61aff785767a0db6a0dafe517eee343442373 100644 (file)
@@ -941,6 +941,10 @@ EXPORT_SYMBOL(drm_mode_create_tv_properties);
  *
  * Called by a driver the first time it's needed, must be attached to desired
  * connectors.
+ *
+ * Atomic drivers should use drm_connector_attach_scaling_mode_property()
+ * instead to correctly assign &drm_connector_state.picture_aspect_ratio
+ * in the atomic state.
  */
 int drm_mode_create_scaling_mode_property(struct drm_device *dev)
 {
@@ -960,6 +964,66 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev)
 }
 EXPORT_SYMBOL(drm_mode_create_scaling_mode_property);
 
+/**
+ * drm_connector_attach_scaling_mode_property - attach atomic scaling mode property
+ * @connector: connector to attach scaling mode property on.
+ * @scaling_mode_mask: or'ed mask of BIT(%DRM_MODE_SCALE_\*).
+ *
+ * This is used to add support for scaling mode to atomic drivers.
+ * The scaling mode will be set to &drm_connector_state.picture_aspect_ratio
+ * and can be used from &drm_connector_helper_funcs->atomic_check for validation.
+ *
+ * This is the atomic version of drm_mode_create_scaling_mode_property().
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
+                                              u32 scaling_mode_mask)
+{
+       struct drm_device *dev = connector->dev;
+       struct drm_property *scaling_mode_property;
+       int i, j = 0;
+       const unsigned valid_scaling_mode_mask =
+               (1U << ARRAY_SIZE(drm_scaling_mode_enum_list)) - 1;
+
+       if (WARN_ON(hweight32(scaling_mode_mask) < 2 ||
+                   scaling_mode_mask & ~valid_scaling_mode_mask))
+               return -EINVAL;
+
+       scaling_mode_property =
+               drm_property_create(dev, DRM_MODE_PROP_ENUM, "scaling mode",
+                                   hweight32(scaling_mode_mask));
+
+       if (!scaling_mode_property)
+               return -ENOMEM;
+
+       for (i = 0; i < ARRAY_SIZE(drm_scaling_mode_enum_list); i++) {
+               int ret;
+
+               if (!(BIT(i) & scaling_mode_mask))
+                       continue;
+
+               ret = drm_property_add_enum(scaling_mode_property, j++,
+                                           drm_scaling_mode_enum_list[i].type,
+                                           drm_scaling_mode_enum_list[i].name);
+
+               if (ret) {
+                       drm_property_destroy(dev, scaling_mode_property);
+
+                       return ret;
+               }
+       }
+
+       drm_object_attach_property(&connector->base,
+                                  scaling_mode_property, 0);
+
+       connector->scaling_mode_property = scaling_mode_property;
+
+       return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
+
 /**
  * drm_mode_create_aspect_ratio_property - create aspect ratio property
  * @dev: DRM device