diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 9f80708e3a77..c424c1948b4e 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -979,6 +979,12 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, * now?) atomic writes to DPMS property: */ return -EINVAL; + } else if (property == connector->content_protection_property) { + if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) { + DRM_DEBUG_KMS("only drivers can set CP Enabled\n"); + return -EINVAL; + } + state->content_protection = val; } else if (property == config->tv_select_subconnector_property) { state->tv.subconnector = val; } else if (property == config->tv_left_margin_property) { @@ -1042,6 +1048,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = (state->crtc) ? state->crtc->base.id : 0; } else if (property == config->dpms_property) { *val = connector->dpms; + } else if (property == connector->content_protection_property) { + *val = state->content_protection; } else if (property == config->tv_select_subconnector_property) { *val = state->tv.subconnector; } else if (property == config->tv_left_margin_property) { diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index fd84556e2bf3..173a52afd21d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1988,6 +1988,42 @@ int drm_mode_create_scaling_mode_property(struct drm_device *dev) } EXPORT_SYMBOL(drm_mode_create_scaling_mode_property); +/** + * drm_connector_attach_content_protection_property - attach content protection + * property + * + * @connector: connector to attach CP property on. + * + * This is used to add support for content protection on select connectors. + * Content Protection is intentionally vague to allow for different underlying + * technologies, however it is most implemented by HDCP. + * + * The content protection will be set to &drm_connector_state.content_protection + * + * Returns: + * Zero on success, negative errno on failure. + */ +int drm_connector_attach_content_protection_property( + struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *prop; + + prop = drm_property_create_enum(dev, 0, "Content Protection", + drm_cp_enum_list, + ARRAY_SIZE(drm_cp_enum_list)); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&connector->base, prop, + DRM_MODE_CONTENT_PROTECTION_UNDESIRED); + + connector->content_protection_property = prop; + + return 0; +} +EXPORT_SYMBOL(drm_connector_attach_content_protection_property); + /** * drm_mode_create_aspect_ratio_property - create aspect ratio property * @dev: DRM device diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index e7fb665befea..9b2d4b6766a9 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -716,6 +716,12 @@ struct drm_connector_state { struct drm_atomic_state *state; + /** + * @content_protection: Connector property to request content + * protection. This is most commonly used for HDCP. + */ + unsigned int content_protection; + struct drm_tv_connector_state tv; /** @@ -946,6 +952,7 @@ struct drm_encoder { * @tile_v_loc: vertical location of this tile * @tile_h_size: horizontal size of this tile. * @tile_v_size: vertical size of this tile. + * @content_protection_property: Optional property to control content protection * * 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 @@ -989,6 +996,12 @@ struct drm_connector { struct drm_property_blob *edid_blob_ptr; struct drm_object_properties properties; + /** + * @content_protection_property: DRM ENUM property for content + * protection + */ + struct drm_property *content_protection_property; + struct drm_property_blob *path_blob_ptr; struct drm_property_blob *tile_blob_ptr; @@ -1840,6 +1853,7 @@ extern const char *drm_get_dvi_i_subconnector_name(int val); extern const char *drm_get_dvi_i_select_name(int val); extern const char *drm_get_tv_subconnector_name(int val); extern const char *drm_get_tv_select_name(int val); +extern const char *drm_get_content_protection_name(int val); extern const char *drm_get_connector_name(int val); extern void drm_fb_release(struct drm_file *file_priv); extern void drm_property_destroy_user_blobs(struct drm_device *dev, @@ -1937,6 +1951,8 @@ extern int drm_mode_create_tv_properties(struct drm_device *dev, unsigned int num_modes, const char * const modes[]); extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); +extern int drm_connector_attach_content_protection_property( + struct drm_connector *connector); extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev); diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index e2f7b7ced60f..ddb2bcf97760 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -117,6 +117,11 @@ #define DRM_MODE_DIRTY_ON 1 #define DRM_MODE_DIRTY_ANNOTATE 2 +/* Content Protection Flags */ +#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED 0 +#define DRM_MODE_CONTENT_PROTECTION_DESIRED 1 +#define DRM_MODE_CONTENT_PROTECTION_ENABLED 2 + struct drm_mode_modeinfo { __u32 clock; __u16 hdisplay;