Skip to content

Commit

Permalink
drm/i915/hdcp: Use HDCP helpers for i915
Browse files Browse the repository at this point in the history
Now that all of the HDCP 1.x logic has been migrated to the central HDCP
helpers, use it in the i915 driver.

The majority of the driver code for HDCP 1.x will live in intel_hdcp.c,
however there are a few helper hooks which are connector-specific and
need to be partially or fully implemented in the intel_dp_hdcp.c or
intel_hdmi.c.

We'll leave most of the HDCP 2.x code alone since we don't have another
implementation of HDCP 2.x to use as reference for what should and
should not live in the drm helpers. The helper will call the overly
general enable/disable/is_capable HDCP 2.x callbacks and leave the
interesting stuff for the driver. Once we have another HDCP 2.x
implementation, we should do a similar migration.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
  • Loading branch information
atseanpaul authored and intel-lab-lkp committed Sep 13, 2021
1 parent 769eacf commit 995396b
Show file tree
Hide file tree
Showing 8 changed files with 413 additions and 1,259 deletions.
29 changes: 21 additions & 8 deletions drivers/gpu/drm/i915/display/intel_ddi.c
Expand Up @@ -26,6 +26,7 @@
*/

#include <drm/drm_scdc_helper.h>
#include <drm/drm_hdcp.h>

#include "i915_drv.h"
#include "intel_audio.h"
Expand Down Expand Up @@ -3131,6 +3132,9 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

drm_WARN_ON(state->base.dev, crtc_state->has_pch_encoder);

if (!crtc_state->bigjoiner_slave)
Expand All @@ -3147,12 +3151,10 @@ static void intel_enable_ddi(struct intel_atomic_state *state,
else
intel_enable_ddi_dp(state, encoder, crtc_state, 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),
crtc_state,
(u8)conn_state->hdcp_content_type);
if (connector->hdcp_helper_data)
drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data,
&state->base,
&dig_port->hdcp_mutex);
}

static void intel_disable_ddi_dp(struct intel_atomic_state *state,
Expand Down Expand Up @@ -3212,7 +3214,13 @@ static void intel_disable_ddi(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
intel_hdcp_disable(to_intel_connector(old_conn_state->connector));
struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

if (connector->hdcp_helper_data)
drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data,
&state->base,
&dig_port->hdcp_mutex);

if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI))
intel_disable_ddi_hdmi(state, encoder, old_crtc_state,
Expand Down Expand Up @@ -3243,13 +3251,18 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
struct intel_connector *connector = to_intel_connector(conn_state->connector);
struct intel_digital_port *dig_port = enc_to_dig_port(encoder);

if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
!intel_encoder_is_mst(encoder))
intel_ddi_update_pipe_dp(state, encoder, crtc_state,
conn_state);

intel_hdcp_update_pipe(state, encoder, crtc_state, conn_state);
if (connector->hdcp_helper_data)
drm_hdcp_helper_atomic_commit(connector->hdcp_helper_data,
&state->base,
&dig_port->hdcp_mutex);
}

static void
Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/i915/display/intel_display_debugfs.c
Expand Up @@ -5,6 +5,7 @@

#include <drm/drm_debugfs.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_hdcp.h>

#include "i915_debugfs.h"
#include "intel_display_debugfs.h"
Expand Down Expand Up @@ -652,10 +653,11 @@ static void intel_hdcp_info(struct seq_file *m,
goto out;
}

ret = intel_hdcp_capable(intel_connector, &hdcp_cap);
ret = drm_hdcp_helper_hdcp1_capable(intel_connector->hdcp_helper_data,
&hdcp_cap);
if (ret)
hdcp_cap = false;
ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap);
ret = intel_hdcp2_capable(&intel_connector->base, &hdcp2_cap);
if (ret)
hdcp2_cap = false;

Expand Down
58 changes: 1 addition & 57 deletions drivers/gpu/drm/i915/display/intel_display_types.h
Expand Up @@ -357,70 +357,13 @@ enum check_link_response {
* - Receiver register masks/offsets
* For instance, the ready bit for the KSV fifo is in a different
* place on DP vs HDMI
* - Receiver register names
* Seriously. In the DP spec, the 16-bit register containing
* downstream information is called BINFO, on HDMI it's called
* BSTATUS. To confuse matters further, DP has a BSTATUS register
* with a completely different definition.
* - KSV FIFO
* On HDMI, the ksv fifo is read all at once, whereas on DP it must
* be read 3 keys at a time
* - Aksv output
* Since Aksv is hidden in hardware, there's different procedures
* to send it over DP AUX vs DDC
*/
struct intel_hdcp_shim {
/* Outputs the transmitter's An and Aksv values to the receiver. */
int (*write_an_aksv)(struct intel_digital_port *dig_port, u8 *an);

/* Reads the receiver's key selection vector */
int (*read_bksv)(struct intel_digital_port *dig_port, u8 *bksv);

/*
* Reads BINFO from DP receivers and BSTATUS from HDMI receivers. The
* definitions are the same in the respective specs, but the names are
* different. Call it BSTATUS since that's the name the HDMI spec
* uses and it was there first.
*/
int (*read_bstatus)(struct intel_digital_port *dig_port,
u8 *bstatus);

/* Determines whether a repeater is present downstream */
int (*repeater_present)(struct intel_digital_port *dig_port,
bool *repeater_present);

/* Reads the receiver's Ri' value */
int (*read_ri_prime)(struct intel_digital_port *dig_port, u8 *ri);

/* Determines if the receiver's KSV FIFO is ready for consumption */
int (*read_ksv_ready)(struct intel_digital_port *dig_port,
bool *ksv_ready);

/* Reads the ksv fifo for num_downstream devices */
int (*read_ksv_fifo)(struct intel_digital_port *dig_port,
int num_downstream, u8 *ksv_fifo);

/* Reads a 32-bit part of V' from the receiver */
int (*read_v_prime_part)(struct intel_digital_port *dig_port,
int i, u32 *part);

/* Enables HDCP signalling on the port */
int (*toggle_signalling)(struct intel_digital_port *dig_port,
enum transcoder cpu_transcoder,
bool enable);

/* Enable/Disable stream encryption on DP MST Transport Link */
int (*stream_encryption)(struct intel_connector *connector,
bool enable);

/* Ensures the link is still protected */
bool (*check_link)(struct intel_digital_port *dig_port,
struct intel_connector *connector);

/* Detects panel's hdcp capability. This is optional for HDMI. */
int (*hdcp_capable)(struct intel_digital_port *dig_port,
bool *hdcp_capable);

/* HDCP adaptation(DP/HDMI) required on the port */
enum hdcp_wired_protocol protocol;

Expand Down Expand Up @@ -550,6 +493,7 @@ struct intel_connector {
struct work_struct modeset_retry_work;

struct intel_hdcp hdcp;
struct drm_hdcp_helper_data *hdcp_helper_data;
};

struct intel_digital_connector_state {
Expand Down

0 comments on commit 995396b

Please sign in to comment.