drm/atomic: Add support for custom scaling mode properties, v2
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 1 May 2017 13:37:54 +0000 (15:37 +0200)
committerMaarten Lankhorst <maarten.lankhorst@linux.intel.com>
Mon, 8 May 2017 11:20:43 +0000 (13:20 +0200)
Some connectors may not allow all scaling mode properties, this function will allow
creating the scaling mode property with only the supported subset. It also wires up
this state for atomic.

This will make it possible to convert i915 connectors to atomic.

Changes since v1:
 - Add DRM_MODE_PROP_ENUM flag to drm_property_create
 - Use the correct index in drm_property_add_enum.
 - Add DocBook for function (Sean Paul).
 - Warn if less than 2 valid scaling modes are passed.
 - Remove level of indent. (Sean Paul)

Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170501133804.8116-3-maarten.lankhorst@linux.intel.com
[mlankhorst: Rename function, fix docbook issues]
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_connector.c
include/drm/drm_connector.h

index 461237cc25bd5ed96c6c4647d90876cfb566aec7..cdec19a86af374c93cf028ad13e0e6276aa2665f 100644 (file)
@@ -1190,6 +1190,8 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
                        state->link_status = val;
        } else if (property == config->aspect_ratio_property) {
                state->picture_aspect_ratio = val;
+       } else if (property == connector->scaling_mode_property) {
+               state->scaling_mode = val;
        } else if (connector->funcs->atomic_set_property) {
                return connector->funcs->atomic_set_property(connector,
                                state, property, val);
@@ -1268,6 +1270,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
                *val = state->link_status;
        } else if (property == config->aspect_ratio_property) {
                *val = state->picture_aspect_ratio;
+       } else if (property == connector->scaling_mode_property) {
+               *val = state->scaling_mode;
        } else if (connector->funcs->atomic_get_property) {
                return connector->funcs->atomic_get_property(connector,
                                state, property, val);
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
index 1ecf5f2619c03543fd90bf1cec1136c52aaa5766..9c15993b907147591f27c982f979f8d92585b2c3 100644 (file)
@@ -332,10 +332,16 @@ struct drm_connector_state {
         * @picture_aspect_ratio: Connector property to control the
         * HDMI infoframe aspect ratio setting.
         *
-        * The DRM_MODE_PICTURE_ASPECT_\* values much match the
+        * The %DRM_MODE_PICTURE_ASPECT_\* values much match the
         * values for &enum hdmi_picture_aspect
         */
        enum hdmi_picture_aspect picture_aspect_ratio;
+
+       /**
+        * @scaling_mode: Connector property to control the
+        * upscaling, mostly used for built-in panels.
+        */
+       unsigned int scaling_mode;
 };
 
 /**
@@ -685,6 +691,7 @@ struct drm_cmdline_mode {
  * @tile_v_loc: vertical location of this tile
  * @tile_h_size: horizontal size of this tile.
  * @tile_v_size: vertical size of this tile.
+ * @scaling_mode_property:  Optional atomic property to control the upscaling.
  *
  * Each connector may be connected to one or more CRTCs, or may be clonable by
  * another connector if they can share a CRTC.  Each connector also has a specific
@@ -764,6 +771,8 @@ struct drm_connector {
        struct drm_property_blob *edid_blob_ptr;
        struct drm_object_properties properties;
 
+       struct drm_property *scaling_mode_property;
+
        /**
         * @path_blob_ptr:
         *
@@ -963,6 +972,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
                                  unsigned int num_modes,
                                  const char * const modes[]);
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
+int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
+                                              u32 scaling_mode_mask);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
 int drm_mode_create_suggested_offset_properties(struct drm_device *dev);