From 8f6e1e22e7d0d4697120e82845036db4f9e4de5b Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Mon, 1 May 2017 15:37:54 +0200 Subject: drm/atomic: Add support for custom scaling mode properties, v2 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 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 --- drivers/gpu/drm/drm_atomic.c | 4 +++ drivers/gpu/drm/drm_connector.c | 64 +++++++++++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 13 ++++++++- 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 461237cc25bd..cdec19a86af3 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -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); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 9f847615ac74..5cd61aff7857 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -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 diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 1ecf5f2619c0..9c15993b9071 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -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); -- cgit v1.2.3