@@ -36,6 +36,7 @@
#include "intel_dp.h"
#include "intel_dp_mst.h"
#include "intel_dpio_phy.h"
+#include "intel_hdcp.h"
static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder,
struct intel_crtc_state *crtc_state,
@@ -215,6 +216,8 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder,
DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
+ intel_hdcp_disable(intel_mst->connector);
+
drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port);
ret = drm_dp_update_payload_part1(&intel_dp->mst_mgr);
@@ -378,6 +381,13 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder,
drm_dp_update_payload_part2(&intel_dp->mst_mgr);
if (pipe_config->has_audio)
intel_audio_codec_enable(encoder, pipe_config, conn_state);
+
+ /* Enable hdcp if it's desired */
+ if (conn_state->content_protection ==
+ DRM_MODE_CONTENT_PROTECTION_DESIRED)
+ intel_hdcp_enable(to_intel_connector(conn_state->connector),
+ pipe_config->cpu_transcoder,
+ (u8)conn_state->hdcp_content_type);
}
static bool intel_dp_mst_enc_get_hw_state(struct intel_encoder *encoder,
@@ -522,11 +532,84 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
return false;
}
+static int
+intel_dp_mst_hdcp_toggle_signalling(struct intel_digital_port *intel_dig_port,
+ enum transcoder cpu_transcoder,
+ bool enable)
+{
+ int ret;
+
+ ret = intel_ddi_toggle_hdcp_signalling(&intel_dig_port->base,
+ cpu_transcoder, enable);
+ if (ret)
+ DRM_DEBUG_KMS("%s HDCP signalling failed (%d)\n",
+ enable ? "Enable" : "Disable", ret);
+ return ret;
+}
+
+static
+int intel_dp_mst_hdcp2_write_msg(struct intel_digital_port *intel_dig_port,
+ void *buf, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
+static
+int intel_dp_mst_hdcp2_read_msg(struct intel_digital_port *intel_dig_port,
+ u8 msg_id, void *buf, size_t size)
+{
+ return -EOPNOTSUPP;
+}
+
+static int
+intel_dp_mst_hdcp2_config_stream_type(struct intel_digital_port *intel_dig_port,
+ bool is_repeater, u8 content_type)
+{
+ return -EOPNOTSUPP;
+}
+
+static
+int intel_dp_mst_hdcp2_check_link(struct intel_digital_port *intel_dig_port)
+{
+ return -EOPNOTSUPP;
+}
+
+static
+int intel_dp_mst_hdcp2_capable(struct intel_digital_port *intel_dig_port,
+ bool *capable)
+{
+ *capable = false;
+ return 0;
+}
+
+static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
+ .write_an_aksv = intel_dp_hdcp_write_an_aksv,
+ .read_bksv = intel_dp_hdcp_read_bksv,
+ .read_bstatus = intel_dp_hdcp_read_bstatus,
+ .repeater_present = intel_dp_hdcp_repeater_present,
+ .read_ri_prime = intel_dp_hdcp_read_ri_prime,
+ .read_ksv_ready = intel_dp_hdcp_read_ksv_ready,
+ .read_ksv_fifo = intel_dp_hdcp_read_ksv_fifo,
+ .read_v_prime_part = intel_dp_hdcp_read_v_prime_part,
+ .toggle_signalling = intel_dp_mst_hdcp_toggle_signalling,
+ .check_link = intel_dp_hdcp_check_link,
+ .hdcp_capable = intel_dp_hdcp_capable,
+
+ .write_2_2_msg = intel_dp_mst_hdcp2_write_msg,
+ .read_2_2_msg = intel_dp_mst_hdcp2_read_msg,
+ .config_stream_type = intel_dp_mst_hdcp2_config_stream_type,
+ .check_2_2_link = intel_dp_mst_hdcp2_check_link,
+ .hdcp_2_2_capable = intel_dp_mst_hdcp2_capable,
+
+ .protocol = HDCP_PROTOCOL_DP,
+};
+
static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *pathprop)
{
struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct drm_device *dev = intel_dig_port->base.base.dev;
+ struct intel_encoder *intel_encoder = &intel_dig_port->base;
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_connector *intel_connector;
struct drm_connector *connector;
@@ -571,6 +654,12 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
intel_attach_force_audio_property(connector);
intel_attach_broadcast_rgb_property(connector);
+ if (is_hdcp_supported(dev_priv, intel_encoder->port)) {
+ int ret = intel_hdcp_init(intel_connector, &intel_dp_hdcp_shim);
+ if (ret)
+ DRM_DEBUG_KMS("HDCP init failed, skipping.\n");
+ }
+
/*
* Reuse the prop from the SST connector because we're
* not allowed to create new props after device registration.