diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 67b330dbf628..142e46e1441d 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -793,6 +793,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, state->privacy_screen_sw_state = val; } else if (property == connector->broadcast_rgb_property) { state->hdmi.broadcast_rgb = val; + } else if (property == connector->rotation_property) { + state->rotation = val; } else if (connector->funcs->atomic_set_property) { return connector->funcs->atomic_set_property(connector, state, property, val); @@ -884,6 +886,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->privacy_screen_sw_state; } else if (property == connector->broadcast_rgb_property) { *val = state->hdmi.broadcast_rgb; + } else if (property == connector->rotation_property) { + *val = state->rotation; } else if (connector->funcs->atomic_get_property) { return connector->funcs->atomic_get_property(connector, state, property, val); diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index 8ec7ee0745c7..e802c9f0331a 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -241,6 +241,16 @@ int drm_plane_create_alpha_property(struct drm_plane *plane) } EXPORT_SYMBOL(drm_plane_create_alpha_property); +static const struct drm_prop_enum_list drm_rotate_props[] = { + { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" }, + { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" }, + { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" }, + { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, + { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, + { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, + { __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" }, +}; + /** * drm_plane_create_rotation_property - create a new rotation property * @plane: drm plane @@ -281,15 +291,6 @@ int drm_plane_create_rotation_property(struct drm_plane *plane, unsigned int rotation, unsigned int supported_rotations) { - static const struct drm_prop_enum_list props[] = { - { __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" }, - { __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" }, - { __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" }, - { __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" }, - { __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" }, - { __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" }, - { __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" }, - }; struct drm_property *prop; WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0); @@ -297,7 +298,8 @@ int drm_plane_create_rotation_property(struct drm_plane *plane, WARN_ON(rotation & ~supported_rotations); prop = drm_property_create_bitmask(plane->dev, 0, "rotation", - props, ARRAY_SIZE(props), + drm_rotate_props, + ARRAY_SIZE(drm_rotate_props), supported_rotations); if (!prop) return -ENOMEM; @@ -313,6 +315,34 @@ int drm_plane_create_rotation_property(struct drm_plane *plane, } EXPORT_SYMBOL(drm_plane_create_rotation_property); +int drm_connector_create_rotation_property(struct drm_connector *conn, + unsigned int rotation, + unsigned int supported_rotations) +{ + struct drm_property *prop; + + WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0); + WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK)); + WARN_ON(rotation & ~supported_rotations); + + prop = drm_property_create_bitmask(conn->dev, 0, "rotation", + drm_rotate_props, + ARRAY_SIZE(drm_rotate_props), + supported_rotations); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&conn->base, prop, rotation); + + if (conn->state) + conn->state->rotation = rotation; + + conn->rotation_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_connector_create_rotation_property); + /** * drm_rotation_simplify() - Try to simplify the rotation * @rotation: Rotation to be simplified diff --git a/include/drm/drm_blend.h b/include/drm/drm_blend.h index 88bdfec3bd88..a84c58f3f13c 100644 --- a/include/drm/drm_blend.h +++ b/include/drm/drm_blend.h @@ -34,6 +34,7 @@ struct drm_device; struct drm_atomic_state; struct drm_plane; +struct drm_connector; static inline bool drm_rotation_90_or_270(unsigned int rotation) { @@ -58,4 +59,8 @@ int drm_atomic_normalize_zpos(struct drm_device *dev, struct drm_atomic_state *state); int drm_plane_create_blend_mode_property(struct drm_plane *plane, unsigned int supported_modes); + +int drm_connector_create_rotation_property(struct drm_connector *conn, + unsigned int rotation, + unsigned int supported_rotations); #endif diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 8f34f4b8183d..bd0fe8a8b9ef 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1149,6 +1149,11 @@ struct drm_connector_state { * @drm_atomic_helper_connector_hdmi_check(). */ struct drm_connector_hdmi_state hdmi; + + /** + * @rotation: Connector property to rotate the maximum output image. + */ + u32 rotation; }; struct drm_connector_hdmi_audio_funcs { @@ -2103,6 +2108,12 @@ struct drm_connector { */ struct drm_property *broadcast_rgb_property; + /** + * @rotation_property: Optional DRM property controlling rotation of the + * output. + */ + struct drm_property *rotation_property; + #define DRM_CONNECTOR_POLL_HPD (1 << 0) #define DRM_CONNECTOR_POLL_CONNECT (1 << 1) #define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)