Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 933519a5 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/hdcp-2018-02-13' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

Add HDCP support to i915 drm driver.

* tag 'topic/hdcp-2018-02-13' of git://anongit.freedesktop.org/drm/drm-misc: (26 commits)
  drm/i915: fix misalignment in HDCP register def
  drm/i915: Reauthenticate HDCP on failure
  drm/i915: Detect panel's hdcp capability
  drm/i915: Optimize HDCP key load
  drm/i915: Retry HDCP bksv read
  drm/i915: Connector info in HDCP debug msgs
  drm/i915: Stop encryption for repeater with no sink
  drm/i915: Handle failure from 2nd stage HDCP auth
  drm/i915: Downgrade hdcp logs from INFO to DEBUG_KMS
  drm/i915: Restore HDCP DRM_INFO when with no downstream
  drm/i915: Check for downstream topology errors
  drm/i915: Start repeater auth on READY/CP_IRQ
  drm/i915: II stage HDCP auth for repeater only
  drm/i915: Extending HDCP for HSW, BDW and BXT+
  drm/i915/dp: Fix compilation of intel_dp_hdcp_check_link
  drm/i915: Only disable HDCP when it's active
  drm/i915: Don't allow HDCP on PORT E/F
  drm/i915: Implement HDCP for DisplayPort
  drm/i915: Implement HDCP for HDMI
  drm/i915: Add function to output Aksv over GMBUS
  ...
parents 76ea0f33 2834d9df
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1224,6 +1224,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
		state->picture_aspect_ratio = val;
	} else if (property == connector->scaling_mode_property) {
		state->scaling_mode = val;
	} 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 (connector->funcs->atomic_set_property) {
		return connector->funcs->atomic_set_property(connector,
				state, property, val);
@@ -1303,6 +1309,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
		*val = state->picture_aspect_ratio;
	} else if (property == connector->scaling_mode_property) {
		*val = state->scaling_mode;
	} else if (property == connector->content_protection_property) {
		*val = state->content_protection;
	} else if (connector->funcs->atomic_get_property) {
		return connector->funcs->atomic_get_property(connector,
				state, property, val);
+83 −4
Original line number Diff line number Diff line
@@ -761,6 +761,13 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
		 drm_tv_subconnector_enum_list)

static struct drm_prop_enum_list drm_cp_enum_list[] = {
	{ DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
	{ DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
	{ DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
};
DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)

/**
 * DOC: standard connector properties
 *
@@ -822,14 +829,50 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 * 	should update this value using drm_mode_connector_set_tile_property().
 * 	Userspace cannot change this property.
 * link-status:
 *      Connector link-status property to indicate the status of link. The default
 *      value of link-status is "GOOD". If something fails during or after modeset,
 *      the kernel driver may set this to "BAD" and issue a hotplug uevent. Drivers
 *      should update this value using drm_mode_connector_set_link_status_property().
 *      Connector link-status property to indicate the status of link. The
 *      default value of link-status is "GOOD". If something fails during or
 *      after modeset, the kernel driver may set this to "BAD" and issue a
 *      hotplug uevent. Drivers should update this value using
 *      drm_mode_connector_set_link_status_property().
 * non_desktop:
 * 	Indicates the output should be ignored for purposes of displaying a
 * 	standard desktop environment or console. This is most likely because
 * 	the output device is not rectilinear.
 * Content Protection:
 *	This property is used by userspace to request the kernel protect future
 *	content communicated over the link. When requested, kernel will apply
 *	the appropriate means of protection (most often HDCP), and use the
 *	property to tell userspace the protection is active.
 *
 *	Drivers can set this up by calling
 *	drm_connector_attach_content_protection_property() on initialization.
 *
 *	The value of this property can be one of the following:
 *
 *	- DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
 *		The link is not protected, content is transmitted in the clear.
 *	- DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
 *		Userspace has requested content protection, but the link is not
 *		currently protected. When in this state, kernel should enable
 *		Content Protection as soon as possible.
 *	- DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
 *		Userspace has requested content protection, and the link is
 *		protected. Only the driver can set the property to this value.
 *		If userspace attempts to set to ENABLED, kernel will return
 *		-EINVAL.
 *
 *	A few guidelines:
 *
 *	- DESIRED state should be preserved until userspace de-asserts it by
 *	  setting the property to UNDESIRED. This means ENABLED should only
 *	  transition to UNDESIRED when the user explicitly requests it.
 *	- If the state is DESIRED, kernel should attempt to re-authenticate the
 *	  link whenever possible. This includes across disable/enable, dpms,
 *	  hotplug, downstream device changes, link status failures, etc..
 *	- Userspace is responsible for polling the property to determine when
 *	  the value transitions from ENABLED to DESIRED. This signifies the link
 *	  is no longer protected and userspace should take appropriate action
 *	  (whatever that might be).
 *
 * Connectors also have one standardized atomic property:
 *
@@ -1130,6 +1173,42 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
}
EXPORT_SYMBOL(drm_connector_attach_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
+1 −0
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ i915-y += intel_audio.o \
	  intel_fbc.o \
	  intel_fifo_underrun.o \
	  intel_frontbuffer.o \
	  intel_hdcp.o \
	  intel_hotplug.o \
	  intel_modes.o \
	  intel_overlay.o \
+1 −0
Original line number Diff line number Diff line
@@ -3661,6 +3661,7 @@ extern int intel_setup_gmbus(struct drm_i915_private *dev_priv);
extern void intel_teardown_gmbus(struct drm_i915_private *dev_priv);
extern bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv,
				     unsigned int pin);
extern int intel_gmbus_output_aksv(struct i2c_adapter *adapter);

extern struct i2c_adapter *
intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin);
+85 −0
Original line number Diff line number Diff line
@@ -3074,6 +3074,7 @@ enum i915_power_well_id {
# define GPIO_DATA_PULLUP_DISABLE	(1 << 13)

#define GMBUS0			_MMIO(dev_priv->gpio_mmio_base + 0x5100) /* clock/port select */
#define   GMBUS_AKSV_SELECT	(1<<11)
#define   GMBUS_RATE_100KHZ	(0<<8)
#define   GMBUS_RATE_50KHZ	(1<<8)
#define   GMBUS_RATE_400KHZ	(2<<8) /* reserved on Pineview */
@@ -8165,6 +8166,7 @@ enum {
#define     GEN9_MEM_LATENCY_LEVEL_1_5_SHIFT	8
#define     GEN9_MEM_LATENCY_LEVEL_2_6_SHIFT	16
#define     GEN9_MEM_LATENCY_LEVEL_3_7_SHIFT	24
#define   SKL_PCODE_LOAD_HDCP_KEYS		0x5
#define   SKL_PCODE_CDCLK_CONTROL		0x7
#define     SKL_CDCLK_PREPARE_FOR_CHANGE	0x3
#define     SKL_CDCLK_READY_FOR_CHANGE		0x1
@@ -8480,6 +8482,88 @@ enum skl_power_gate {
#define   CNL_AUX_ANAOVRD1_ENABLE	(1<<16)
#define   CNL_AUX_ANAOVRD1_LDO_BYPASS	(1<<23)

/* HDCP Key Registers */
#define HDCP_KEY_CONF			_MMIO(0x66c00)
#define  HDCP_AKSV_SEND_TRIGGER		BIT(31)
#define  HDCP_CLEAR_KEYS_TRIGGER	BIT(30)
#define  HDCP_KEY_LOAD_TRIGGER		BIT(8)
#define HDCP_KEY_STATUS			_MMIO(0x66c04)
#define  HDCP_FUSE_IN_PROGRESS		BIT(7)
#define  HDCP_FUSE_ERROR		BIT(6)
#define  HDCP_FUSE_DONE			BIT(5)
#define  HDCP_KEY_LOAD_STATUS		BIT(1)
#define  HDCP_KEY_LOAD_DONE		BIT(0)
#define HDCP_AKSV_LO			_MMIO(0x66c10)
#define HDCP_AKSV_HI			_MMIO(0x66c14)

/* HDCP Repeater Registers */
#define HDCP_REP_CTL			_MMIO(0x66d00)
#define  HDCP_DDIB_REP_PRESENT		BIT(30)
#define  HDCP_DDIA_REP_PRESENT		BIT(29)
#define  HDCP_DDIC_REP_PRESENT		BIT(28)
#define  HDCP_DDID_REP_PRESENT		BIT(27)
#define  HDCP_DDIF_REP_PRESENT		BIT(26)
#define  HDCP_DDIE_REP_PRESENT		BIT(25)
#define  HDCP_DDIB_SHA1_M0		(1 << 20)
#define  HDCP_DDIA_SHA1_M0		(2 << 20)
#define  HDCP_DDIC_SHA1_M0		(3 << 20)
#define  HDCP_DDID_SHA1_M0		(4 << 20)
#define  HDCP_DDIF_SHA1_M0		(5 << 20)
#define  HDCP_DDIE_SHA1_M0		(6 << 20) /* Bspec says 5? */
#define  HDCP_SHA1_BUSY			BIT(16)
#define  HDCP_SHA1_READY		BIT(17)
#define  HDCP_SHA1_COMPLETE		BIT(18)
#define  HDCP_SHA1_V_MATCH		BIT(19)
#define  HDCP_SHA1_TEXT_32		(1 << 1)
#define  HDCP_SHA1_COMPLETE_HASH	(2 << 1)
#define  HDCP_SHA1_TEXT_24		(4 << 1)
#define  HDCP_SHA1_TEXT_16		(5 << 1)
#define  HDCP_SHA1_TEXT_8		(6 << 1)
#define  HDCP_SHA1_TEXT_0		(7 << 1)
#define HDCP_SHA_V_PRIME_H0		_MMIO(0x66d04)
#define HDCP_SHA_V_PRIME_H1		_MMIO(0x66d08)
#define HDCP_SHA_V_PRIME_H2		_MMIO(0x66d0C)
#define HDCP_SHA_V_PRIME_H3		_MMIO(0x66d10)
#define HDCP_SHA_V_PRIME_H4		_MMIO(0x66d14)
#define HDCP_SHA_V_PRIME(h)		_MMIO((0x66d04 + h * 4))
#define HDCP_SHA_TEXT			_MMIO(0x66d18)

/* HDCP Auth Registers */
#define _PORTA_HDCP_AUTHENC		0x66800
#define _PORTB_HDCP_AUTHENC		0x66500
#define _PORTC_HDCP_AUTHENC		0x66600
#define _PORTD_HDCP_AUTHENC		0x66700
#define _PORTE_HDCP_AUTHENC		0x66A00
#define _PORTF_HDCP_AUTHENC		0x66900
#define _PORT_HDCP_AUTHENC(port, x)	_MMIO(_PICK(port, \
					  _PORTA_HDCP_AUTHENC, \
					  _PORTB_HDCP_AUTHENC, \
					  _PORTC_HDCP_AUTHENC, \
					  _PORTD_HDCP_AUTHENC, \
					  _PORTE_HDCP_AUTHENC, \
					  _PORTF_HDCP_AUTHENC) + x)
#define PORT_HDCP_CONF(port)		_PORT_HDCP_AUTHENC(port, 0x0)
#define  HDCP_CONF_CAPTURE_AN		BIT(0)
#define  HDCP_CONF_AUTH_AND_ENC		(BIT(1) | BIT(0))
#define PORT_HDCP_ANINIT(port)		_PORT_HDCP_AUTHENC(port, 0x4)
#define PORT_HDCP_ANLO(port)		_PORT_HDCP_AUTHENC(port, 0x8)
#define PORT_HDCP_ANHI(port)		_PORT_HDCP_AUTHENC(port, 0xC)
#define PORT_HDCP_BKSVLO(port)		_PORT_HDCP_AUTHENC(port, 0x10)
#define PORT_HDCP_BKSVHI(port)		_PORT_HDCP_AUTHENC(port, 0x14)
#define PORT_HDCP_RPRIME(port)		_PORT_HDCP_AUTHENC(port, 0x18)
#define PORT_HDCP_STATUS(port)		_PORT_HDCP_AUTHENC(port, 0x1C)
#define  HDCP_STATUS_STREAM_A_ENC	BIT(31)
#define  HDCP_STATUS_STREAM_B_ENC	BIT(30)
#define  HDCP_STATUS_STREAM_C_ENC	BIT(29)
#define  HDCP_STATUS_STREAM_D_ENC	BIT(28)
#define  HDCP_STATUS_AUTH		BIT(21)
#define  HDCP_STATUS_ENC		BIT(20)
#define  HDCP_STATUS_RI_MATCH		BIT(19)
#define  HDCP_STATUS_R0_READY		BIT(18)
#define  HDCP_STATUS_AN_READY		BIT(17)
#define  HDCP_STATUS_CIPHER		BIT(16)
#define  HDCP_STATUS_FRAME_CNT(x)	((x >> 8) & 0xff)

/* Per-pipe DDI Function Control */
#define _TRANS_DDI_FUNC_CTL_A		0x60400
#define _TRANS_DDI_FUNC_CTL_B		0x61400
@@ -8511,6 +8595,7 @@ enum skl_power_gate {
#define  TRANS_DDI_EDP_INPUT_A_ONOFF	(4<<12)
#define  TRANS_DDI_EDP_INPUT_B_ONOFF	(5<<12)
#define  TRANS_DDI_EDP_INPUT_C_ONOFF	(6<<12)
#define  TRANS_DDI_HDCP_SIGNALLING	(1<<9)
#define  TRANS_DDI_DP_VC_PAYLOAD_ALLOC	(1<<8)
#define  TRANS_DDI_HDMI_SCRAMBLER_CTS_ENABLE (1<<7)
#define  TRANS_DDI_HDMI_SCRAMBLER_RESET_FREQ (1<<6)
Loading