diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_hdcp.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_hdcp.c | 158 |
1 files changed, 89 insertions, 69 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 2984d2810e42..650232c4892b 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -23,6 +23,7 @@ #include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_hdcp.h" +#include "intel_hdcp_gsc.h" #include "intel_hdcp_regs.h" #include "intel_pcode.h" @@ -203,13 +204,20 @@ bool intel_hdcp2_capable(struct intel_connector *connector) struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; + struct intel_gt *gt = dev_priv->media_gt; + struct intel_gsc_uc *gsc = >->uc.gsc; bool capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) return false; - /* MEI interface is solid */ + /* If MTL+ make sure gsc is loaded and proxy is setup */ + if (intel_hdcp_gsc_cs_required(dev_priv)) + if (!intel_uc_fw_is_running(&gsc->fw)) + return false; + + /* MEI/GSC interface is solid depending on which is used */ mutex_lock(&dev_priv->display.hdcp.comp_mutex); if (!dev_priv->display.hdcp.comp_added || !dev_priv->display.hdcp.master) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); @@ -1142,18 +1150,18 @@ hdcp2_prepare_ake_init(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->initiate_hdcp2_session(comp->mei_dev, data, ake_data); + ret = arbiter->ops->initiate_hdcp2_session(arbiter->hdcp_dev, data, ake_data); if (ret) drm_dbg_kms(&dev_priv->drm, "Prepare_ake_init failed. %d\n", ret); @@ -1172,18 +1180,18 @@ hdcp2_verify_rx_cert_prepare_km(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->verify_receiver_cert_prepare_km(comp->mei_dev, data, + ret = arbiter->ops->verify_receiver_cert_prepare_km(arbiter->hdcp_dev, data, rx_cert, paired, ek_pub_km, msg_sz); if (ret < 0) @@ -1200,18 +1208,18 @@ static int hdcp2_verify_hprime(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->verify_hprime(comp->mei_dev, data, rx_hprime); + ret = arbiter->ops->verify_hprime(arbiter->hdcp_dev, data, rx_hprime); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Verify hprime failed. %d\n", ret); mutex_unlock(&dev_priv->display.hdcp.comp_mutex); @@ -1226,18 +1234,18 @@ hdcp2_store_pairing_info(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->store_pairing_info(comp->mei_dev, data, pairing_info); + ret = arbiter->ops->store_pairing_info(arbiter->hdcp_dev, data, pairing_info); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Store pairing info failed. %d\n", ret); @@ -1253,18 +1261,18 @@ hdcp2_prepare_lc_init(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->initiate_locality_check(comp->mei_dev, data, lc_init); + ret = arbiter->ops->initiate_locality_check(arbiter->hdcp_dev, data, lc_init); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Prepare lc_init failed. %d\n", ret); @@ -1280,18 +1288,18 @@ hdcp2_verify_lprime(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->verify_lprime(comp->mei_dev, data, rx_lprime); + ret = arbiter->ops->verify_lprime(arbiter->hdcp_dev, data, rx_lprime); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Verify L_Prime failed. %d\n", ret); @@ -1306,18 +1314,18 @@ static int hdcp2_prepare_skey(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->get_session_key(comp->mei_dev, data, ske_data); + ret = arbiter->ops->get_session_key(arbiter->hdcp_dev, data, ske_data); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Get session key failed. %d\n", ret); @@ -1335,20 +1343,21 @@ hdcp2_verify_rep_topology_prepare_ack(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->repeater_check_flow_prepare_ack(comp->mei_dev, data, - rep_topology, - rep_send_ack); + ret = arbiter->ops->repeater_check_flow_prepare_ack(arbiter->hdcp_dev, + data, + rep_topology, + rep_send_ack); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Verify rep topology failed. %d\n", ret); @@ -1364,18 +1373,18 @@ hdcp2_verify_mprime(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->verify_mprime(comp->mei_dev, data, stream_ready); + ret = arbiter->ops->verify_mprime(arbiter->hdcp_dev, data, stream_ready); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Verify mprime failed. %d\n", ret); mutex_unlock(&dev_priv->display.hdcp.comp_mutex); @@ -1388,18 +1397,18 @@ static int hdcp2_authenticate_port(struct intel_connector *connector) struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = &dig_port->hdcp_port_data; struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->enable_hdcp_authentication(comp->mei_dev, data); + ret = arbiter->ops->enable_hdcp_authentication(arbiter->hdcp_dev, data); if (ret < 0) drm_dbg_kms(&dev_priv->drm, "Enable hdcp auth failed. %d\n", ret); @@ -1408,22 +1417,22 @@ static int hdcp2_authenticate_port(struct intel_connector *connector) return ret; } -static int hdcp2_close_mei_session(struct intel_connector *connector) +static int hdcp2_close_session(struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct i915_hdcp_comp_master *comp; + struct i915_hdcp_master *arbiter; int ret; mutex_lock(&dev_priv->display.hdcp.comp_mutex); - comp = dev_priv->display.hdcp.master; + arbiter = dev_priv->display.hdcp.master; - if (!comp || !comp->ops) { + if (!arbiter || !arbiter->ops) { mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return -EINVAL; } - ret = comp->ops->close_hdcp_session(comp->mei_dev, + ret = arbiter->ops->close_hdcp_session(arbiter->hdcp_dev, &dig_port->hdcp_port_data); mutex_unlock(&dev_priv->display.hdcp.comp_mutex); @@ -1432,7 +1441,7 @@ static int hdcp2_close_mei_session(struct intel_connector *connector) static int hdcp2_deauthenticate_port(struct intel_connector *connector) { - return hdcp2_close_mei_session(connector); + return hdcp2_close_session(connector); } /* Authentication flow starts from here */ @@ -2142,8 +2151,8 @@ static int i915_hdcp_component_bind(struct device *i915_kdev, drm_dbg(&dev_priv->drm, "I915 HDCP comp bind\n"); mutex_lock(&dev_priv->display.hdcp.comp_mutex); - dev_priv->display.hdcp.master = (struct i915_hdcp_comp_master *)data; - dev_priv->display.hdcp.master->mei_dev = mei_kdev; + dev_priv->display.hdcp.master = (struct i915_hdcp_master *)data; + dev_priv->display.hdcp.master->hdcp_dev = mei_kdev; mutex_unlock(&dev_priv->display.hdcp.comp_mutex); return 0; @@ -2160,30 +2169,30 @@ static void i915_hdcp_component_unbind(struct device *i915_kdev, mutex_unlock(&dev_priv->display.hdcp.comp_mutex); } -static const struct component_ops i915_hdcp_component_ops = { +static const struct component_ops i915_hdcp_ops = { .bind = i915_hdcp_component_bind, .unbind = i915_hdcp_component_unbind, }; -static enum mei_fw_ddi intel_get_mei_fw_ddi_index(enum port port) +static enum hdcp_ddi intel_get_hdcp_ddi_index(enum port port) { switch (port) { case PORT_A: - return MEI_DDI_A; + return HDCP_DDI_A; case PORT_B ... PORT_F: - return (enum mei_fw_ddi)port; + return (enum hdcp_ddi)port; default: - return MEI_DDI_INVALID_PORT; + return HDCP_DDI_INVALID_PORT; } } -static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) +static enum hdcp_transcoder intel_get_hdcp_transcoder(enum transcoder cpu_transcoder) { switch (cpu_transcoder) { case TRANSCODER_A ... TRANSCODER_D: - return (enum mei_fw_tc)(cpu_transcoder | 0x10); + return (enum hdcp_transcoder)(cpu_transcoder | 0x10); default: /* eDP, DSI TRANSCODERS are non HDCP capable */ - return MEI_INVALID_TRANSCODER; + return HDCP_INVALID_TRANSCODER; } } @@ -2197,20 +2206,20 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, enum port port = dig_port->base.port; if (DISPLAY_VER(dev_priv) < 12) - data->fw_ddi = intel_get_mei_fw_ddi_index(port); + data->hdcp_ddi = intel_get_hdcp_ddi_index(port); else /* - * As per ME FW API expectation, for GEN 12+, fw_ddi is filled + * As per ME FW API expectation, for GEN 12+, hdcp_ddi is filled * with zero(INVALID PORT index). */ - data->fw_ddi = MEI_DDI_INVALID_PORT; + data->hdcp_ddi = HDCP_DDI_INVALID_PORT; /* - * As associated transcoder is set and modified at modeset, here fw_tc + * As associated transcoder is set and modified at modeset, here hdcp_transcoder * is initialized to zero (invalid transcoder index). This will be * retained for <Gen12 forever. */ - data->fw_tc = MEI_INVALID_TRANSCODER; + data->hdcp_transcoder = HDCP_INVALID_TRANSCODER; data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED; data->protocol = (u8)shim->protocol; @@ -2232,6 +2241,9 @@ static int initialize_hdcp_port_data(struct intel_connector *connector, static bool is_hdcp2_supported(struct drm_i915_private *dev_priv) { + if (intel_hdcp_gsc_cs_required(dev_priv)) + return true; + if (!IS_ENABLED(CONFIG_INTEL_MEI_HDCP)) return false; @@ -2253,10 +2265,14 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv) dev_priv->display.hdcp.comp_added = true; mutex_unlock(&dev_priv->display.hdcp.comp_mutex); - ret = component_add_typed(dev_priv->drm.dev, &i915_hdcp_component_ops, - I915_COMPONENT_HDCP); + if (intel_hdcp_gsc_cs_required(dev_priv)) + ret = intel_hdcp_gsc_init(dev_priv); + else + ret = component_add_typed(dev_priv->drm.dev, &i915_hdcp_ops, + I915_COMPONENT_HDCP); + if (ret < 0) { - drm_dbg_kms(&dev_priv->drm, "Failed at component add(%d)\n", + drm_dbg_kms(&dev_priv->drm, "Failed at fw component add(%d)\n", ret); mutex_lock(&dev_priv->display.hdcp.comp_mutex); dev_priv->display.hdcp.comp_added = false; @@ -2347,7 +2363,8 @@ int intel_hdcp_enable(struct intel_connector *connector, } if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + dig_port->hdcp_port_data.hdcp_transcoder = + intel_get_hdcp_transcoder(hdcp->cpu_transcoder); /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2482,7 +2499,10 @@ void intel_hdcp_component_fini(struct drm_i915_private *dev_priv) dev_priv->display.hdcp.comp_added = false; mutex_unlock(&dev_priv->display.hdcp.comp_mutex); - component_del(dev_priv->drm.dev, &i915_hdcp_component_ops); + if (intel_hdcp_gsc_cs_required(dev_priv)) + intel_hdcp_gsc_fini(dev_priv); + else + component_del(dev_priv->drm.dev, &i915_hdcp_ops); } void intel_hdcp_cleanup(struct intel_connector *connector) |