[07/10] drm: Add CP downstream_info property

Submitted by Ramalingam C on Feb. 26, 2019, 7:36 a.m.

Details

Message ID 1551166569-19683-8-git-send-email-ramalingam.c@intel.com
State New
Headers show
Series "HDCP2.2 Phase II" ( rev: 1 ) in Intel GFX

Not browsing as part of any series.

Commit Message

Ramalingam C Feb. 26, 2019, 7:36 a.m.
This patch adds CP downstream info blob property to the
connectors. This enables the Userspace to read the information of HDCP
authenticated downstream topology.

Driver will updated this blob with all downstream information at the
end of the authentication.

Userspace need this informations to configure this platform as repeater,
where KMD will be the downstream HDCP ports of the repeater and userspace
implementation will act as upstream HDCP port.

Signed-off-by: Ramalingam C <ramalingam.c@intel.com>
---
 drivers/gpu/drm/drm_atomic_uapi.c |  3 ++
 drivers/gpu/drm/drm_connector.c   | 88 +++++++++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h       | 12 ++++++
 include/uapi/drm/drm_mode.h       | 27 ++++++++++++
 4 files changed, 130 insertions(+)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 9c57d8c07d09..f28fb64d1986 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -842,6 +842,9 @@  drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->cp_content_type;
 	} else if (property == connector->cp_srm_property) {
 		*val = state->cp_srm_blob_id;
+	} else if (property == connector->cp_downstream_property) {
+		*val = connector->cp_downstream_blob_ptr ?
+			connector->cp_downstream_blob_ptr->base.id : 0;
 	} else if (property == config->writeback_fb_id_property) {
 		/* Writeback framebuffer is one-shot, write and forget */
 		*val = 0;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 510941ad532f..0b58d07d1d53 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -245,6 +245,7 @@  int drm_connector_init(struct drm_device *dev,
 	INIT_LIST_HEAD(&connector->modes);
 	mutex_init(&connector->mutex);
 	connector->edid_blob_ptr = NULL;
+	connector->cp_downstream_blob_ptr = NULL;
 	connector->status = connector_status_unknown;
 	connector->display_info.panel_orientation =
 		DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
@@ -1002,6 +1003,25 @@  DRM_ENUM_NAME_FN(drm_get_cp_content_type_name, drm_cp_content_type_enum_list)
  *	Guideline for programming:
  *	  - Property state can be changed only when "Content Protection state is
  *		DRM_MODE_CONTENT_PROTECTION_UNDESIRED.
+ * CP_Downstream_Info:
+ *	This blob property is used to pass the HDCP downstream topology details
+ *	of a HDCP encrypted connector, from kernel to userspace.
+ *	This provides all required information to userspace, so that userspace
+ *	can implement the HDCP repeater using the kernel as downstream ports of
+ *	the repeater. as illustrated below:
+ *
+ *                          HDCP Repeaters
+ * +--------------------------------------------------------------+
+ * |                                                              |
+ * |                               |                              |
+ * |   Userspace HDCP Receiver  +----->    KMD HDCP transmitters  |
+ * |      (Upstream Port)      <------+     (Downstream Ports)    |
+ * |                               |                              |
+ * |                                                              |
+ * +--------------------------------------------------------------+
+ *
+ *	Kernel will populate this blob only when the HDCP authentication is
+ *	successful.
  *
  * max bpc:
  *	This range property is used by userspace to limit the bit depth. When
@@ -1664,6 +1684,74 @@  int drm_connector_attach_cp_srm_property(struct drm_connector *connector)
 EXPORT_SYMBOL(drm_connector_attach_cp_srm_property);
 
 /**
+ * drm_connector_attach_cp_downstream_property - attach cp downstream
+ * property
+ *
+ * @connector: connector to attach cp downstream property on.
+ *
+ * This is used to add support for content protection downstream info on
+ * select connectors. when Intel platform is configured as repeater,
+ * this downstream info is used by userspace, to complete the repeater
+ * authentication of HDCP specification with upstream HDCP transmitter.
+ *
+ * The cp downstream will be set to &drm_connector_state.cp_downstream
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_cp_downstream_property(
+		struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_property *prop;
+
+	prop = drm_property_create(dev, DRM_MODE_PROP_BLOB |
+				   DRM_MODE_PROP_IMMUTABLE,
+				   "CP_Downstream_Info", 0);
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&connector->base, prop, 0);
+
+	connector->cp_downstream_property = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_cp_downstream_property);
+
+/**
+ * drm_mode_connector_update_cp_downstream_property - update the cp_downstream
+ *			property of a connector
+ * @connector: drm connector
+ * @cp_downstream_info: new value of the cp_downstream property
+ *
+ * This function creates a new blob modeset object and assigns its id to the
+ * connector's cp_downstream property.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_connector_update_cp_downstream_property(
+			struct drm_connector *connector,
+			const struct cp_downstream_info *info)
+{
+	struct drm_device *dev = connector->dev;
+	int ret;
+
+	if (!info)
+		return -EINVAL;
+
+	ret = drm_property_replace_global_blob(dev,
+					&connector->cp_downstream_blob_ptr,
+					sizeof(struct cp_downstream_info),
+					info,
+					&connector->base,
+					connector->cp_downstream_property);
+	return ret;
+}
+EXPORT_SYMBOL(drm_mode_connector_update_cp_downstream_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 796e5d5e9e5f..4ea433e779d8 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1060,6 +1060,13 @@  struct drm_connector {
 	struct drm_property *cp_srm_property;
 
 	/**
+	 * @cp_downstream_property: DRM BLOB property for content
+	 * protection downstream information.
+	 */
+	struct drm_property *cp_downstream_property;
+	struct drm_property_blob *cp_downstream_blob_ptr;
+
+	/**
 	 * @path_blob_ptr:
 	 *
 	 * DRM blob property data for the DP MST path property. This should only
@@ -1337,6 +1344,11 @@  int drm_connector_attach_content_protection_property(
 int drm_connector_attach_cp_content_type_property(
 		struct drm_connector *connector);
 int drm_connector_attach_cp_srm_property(struct drm_connector *connector);
+int drm_connector_attach_cp_downstream_property(
+		struct drm_connector *connector);
+int drm_mode_connector_update_cp_downstream_property(
+		struct drm_connector *connector,
+		const struct cp_downstream_info *info);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
 int drm_mode_create_colorspace_property(struct drm_connector *connector);
 int drm_mode_create_content_type_property(struct drm_device *dev);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 8504e3110e19..aae84d025518 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -214,6 +214,33 @@  extern "C" {
 #define DRM_MODE_CP_CONTENT_TYPE0		0
 #define DRM_MODE_CP_CONTENT_TYPE1		1
 
+#define DRM_MODE_HDCP_KSV_LEN			5
+#define DRM_MODE_HDCP_MAX_DEVICE_CNT		127
+
+struct cp_downstream_info {
+	/* KSV of immediate HDCP Sink. In Little-Endian Format. */
+	char bksv[DRM_MODE_HDCP_KSV_LEN];
+
+	/* Whether Immediate HDCP sink is a repeater? */
+	bool is_repeater;
+
+	/* Depth received from immediate downstream repeater */
+	__u8 depth;
+
+	/* Device count received from immediate downstream repeater */
+	__u32 device_count;
+
+	/*
+	 * Max buffer required to hold ksv list received from immediate
+	 * repeater. In this array first device_count * DRM_MODE_HDCP_KSV_LEN
+	 * will hold the valid ksv bytes.
+	 * If authentication specification is
+	 *	HDCP1.4 - each KSV's Bytes will be in Little-Endian format.
+	 *	HDCP2.2 - each KSV's Bytes will be in Big-Endian format.
+	 */
+	char ksv_list[DRM_MODE_HDCP_KSV_LEN * DRM_MODE_HDCP_MAX_DEVICE_CNT];
+};
+
 struct drm_mode_modeinfo {
 	__u32 clock;
 	__u16 hdisplay;