From 23fdbdd7ed3f18f56773c6cbef5d3f1d68befd69 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 8 Jan 2018 14:55:36 -0500 Subject: drm/i915: Add more control to wait_for routines This patch adds a little more control to a couple wait_for routines such that we can avoid open-coding read/wait/timeout patterns which: - need the value of the register after the wait_for - run arbitrary operation for the read portion This patch also chooses the correct sleep function (based on timers-howto.txt) for the polling interval the caller specifies. Changes in v2: - Added to the series Changes in v3: - Rebased on drm-intel-next-queued and the new Wmin/max _wait_for - Removed msleep option Changes in v4: - Removed ; for OP in _wait_for (Chris) - Moved reg_value definition above ret (Chris) Changes in v4: - checkpatch whitespace fix Changes in v5: - None Changes in v6: - None Suggested-by: Chris Wilson Reviewed-by: Daniel Vetter Reviewed-by: Chris Wilson Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20180108195545.218615-3-seanpaul@chromium.org --- drivers/gpu/drm/i915/intel_drv.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 30f791f..9848e8e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -41,20 +41,21 @@ #include /** - * _wait_for - magic (register) wait macro + * __wait_for - magic wait macro * - * Does the right thing for modeset paths when run under kdgb or similar atomic - * contexts. Note that it's important that we check the condition again after - * having timed out, since the timeout could be due to preemption or similar and - * we've never had a chance to check the condition before the timeout. + * Macro to help avoid open coding check/wait/timeout patterns. Note that it's + * important that we check the condition again after having timed out, since the + * timeout could be due to preemption or similar and we've never had a chance to + * check the condition before the timeout. */ -#define _wait_for(COND, US, Wmin, Wmax) ({ \ +#define __wait_for(OP, COND, US, Wmin, Wmax) ({ \ unsigned long timeout__ = jiffies + usecs_to_jiffies(US) + 1; \ long wait__ = (Wmin); /* recommended min for usleep is 10 us */ \ int ret__; \ might_sleep(); \ for (;;) { \ bool expired__ = time_after(jiffies, timeout__); \ + OP; \ if (COND) { \ ret__ = 0; \ break; \ @@ -70,7 +71,9 @@ ret__; \ }) -#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) +#define _wait_for(COND, US, Wmin, Wmax) __wait_for(, (COND), (US), (Wmin), \ + (Wmax)) +#define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) /* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ #if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) -- cgit v1.1 From ee5e5e7a5e0fdeca5add8de6314b1f0a62604bdf Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 8 Jan 2018 14:55:39 -0500 Subject: drm/i915: Add HDCP framework + base implementation This patch adds the framework required to add HDCP support to intel connectors. It implements Aksv loading from fuse, and parts 1/2/3 of the HDCP authentication scheme. Note that without shim implementations, this does not actually implement HDCP. That will come in subsequent patches. Changes in v2: - Don't open code wait_fors (Chris) - drm_hdcp.c under MIT license (Daniel) - Move intel_hdcp_disable() call above ddi_disable (Ram) - Fix // comments (I wore a cone of shame for 12 hours to atone) (Daniel) - Justify intel_hdcp_shim with comments (Daniel) - Fixed async locking issues by adding hdcp_mutex (Daniel) - Don't alter connector_state in enable/disable (Daniel) Changes in v3: - Added hdcp_mutex/hdcp_value to make async reasonable - Added hdcp_prop_work to separate link checking & property setting - Added new helper for atomic_check state tracking (Daniel) - Moved enable/disable into atomic_commit with matching helpers - Moved intel_hdcp_check_link out of all locks when called from dp - Bumped up ksv_fifo timeout (noticed failure on one of my dongles) Changes in v4: - Remove SKL_ prefix from most register names (Daniel) - Move enable/disable back to modeset path (Daniel) - s/get_random_long/get_random_u32/ (Daniel) - Remove mode_config.mutex lock in prop_work (Daniel) - Add intel_hdcp_init to handle init of conn components (Daniel) - Actually check return value of attach_property - Check Bksv is valid before trying to authenticate (Ram) Changes in v5: - checkpatch whitespace changes - s/DRM_MODE_CONTENT_PROTECTION_OFF/DRM_MODE_CONTENT_PROTECTION_UNDESIRED/ - Fix ksv list wait timeout (actually wait 5s) - Increase the R0 timeout to 300ms (Ram) Changes in v6: - SPDX license Cc: Chris Wilson Reviewed-by: Ramalingam C Reviewed-by: Daniel Vetter Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20180108195545.218615-6-seanpaul@chromium.org --- drivers/gpu/drm/i915/intel_drv.h | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9848e8e..c59277c 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -301,6 +301,76 @@ struct intel_panel { } backlight; }; +/* + * This structure serves as a translation layer between the generic HDCP code + * and the bus-specific code. What that means is that HDCP over HDMI differs + * from HDCP over DP, so to account for these differences, we need to + * communicate with the receiver through this shim. + * + * For completeness, the 2 buses differ in the following ways: + * - DP AUX vs. DDC + * HDCP registers on the receiver are set via DP AUX for DP, and + * they are set via DDC for HDMI. + * - Receiver register offsets + * The offsets of the registers are different for DP vs. HDMI + * - 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 *intel_dig_port, u8 *an); + + /* Reads the receiver's key selection vector */ + int (*read_bksv)(struct intel_digital_port *intel_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 *intel_dig_port, + u8 *bstatus); + + /* Determines whether a repeater is present downstream */ + int (*repeater_present)(struct intel_digital_port *intel_dig_port, + bool *repeater_present); + + /* Reads the receiver's Ri' value */ + int (*read_ri_prime)(struct intel_digital_port *intel_dig_port, u8 *ri); + + /* Determines if the receiver's KSV FIFO is ready for consumption */ + int (*read_ksv_ready)(struct intel_digital_port *intel_dig_port, + bool *ksv_ready); + + /* Reads the ksv fifo for num_downstream devices */ + int (*read_ksv_fifo)(struct intel_digital_port *intel_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 *intel_dig_port, + int i, u32 *part); + + /* Enables HDCP signalling on the port */ + int (*toggle_signalling)(struct intel_digital_port *intel_dig_port, + bool enable); + + /* Ensures the link is still protected */ + bool (*check_link)(struct intel_digital_port *intel_dig_port); +}; + struct intel_connector { struct drm_connector base; /* @@ -332,6 +402,12 @@ struct intel_connector { /* Work struct to schedule a uevent on link train failure */ struct work_struct modeset_retry_work; + + const struct intel_hdcp_shim *hdcp_shim; + struct mutex hdcp_mutex; + uint64_t hdcp_value; /* protected by hdcp_mutex */ + struct delayed_work hdcp_check_work; + struct work_struct hdcp_prop_work; }; struct intel_digital_connector_state { @@ -1761,6 +1837,15 @@ static inline void intel_backlight_device_unregister(struct intel_connector *con } #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */ +/* intel_hdcp.c */ +void intel_hdcp_atomic_check(struct drm_connector *connector, + struct drm_connector_state *old_state, + struct drm_connector_state *new_state); +int intel_hdcp_init(struct intel_connector *connector, + const struct intel_hdcp_shim *hdcp_shim); +int intel_hdcp_enable(struct intel_connector *connector); +int intel_hdcp_disable(struct intel_connector *connector); +int intel_hdcp_check_link(struct intel_connector *connector); /* intel_psr.c */ void intel_psr_enable(struct intel_dp *intel_dp, -- cgit v1.1 From 2320175feb74a11d3b287eead09bb5c0953cf27f Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 8 Jan 2018 14:55:42 -0500 Subject: drm/i915: Implement HDCP for HDMI This patch adds HDCP support for HDMI connectors by implementing the intel_hdcp_shim. Nothing too special, just a bunch of DDC reads/writes. Changes in v2: - Rebased on drm-intel-next Changes in v3: - Initialize new worker Changes in v4: - Remove SKL_ prefix from most register names (Daniel) - Wrap sanity checks in WARN_ON (Daniel) - Consolidate the enable/disable functions into one toggle fn - Use intel_hdcp_init (Daniel) Changes in v5: - checkpatch whitespace nits Changes in v6: - None Cc: Daniel Vetter Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20180108195545.218615-9-seanpaul@chromium.org --- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index c59277c..731dc36 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1377,6 +1377,8 @@ void intel_ddi_compute_min_voltage_level(struct drm_i915_private *dev_priv, u32 bxt_signal_levels(struct intel_dp *intel_dp); uint32_t ddi_signal_levels(struct intel_dp *intel_dp); u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); +int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, + bool enable); unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, int plane, unsigned int height); -- cgit v1.1 From fdddd08c4875db0799defd8cad318a68f564e7e5 Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Thu, 18 Jan 2018 11:18:05 +0530 Subject: drm/i915: Extending HDCP for HSW, BDW and BXT+ This patch extends the Key load process and hdcp initialization for few more capable intel platforms i.e. HSW, BDW and BXT+. Signed-off-by: Ramalingam C [seanpaul fixed checkpatch issues] Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/1516254488-4971-2-git-send-email-ramalingam.c@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 731dc36..9461777 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1848,6 +1848,7 @@ int intel_hdcp_init(struct intel_connector *connector, int intel_hdcp_enable(struct intel_connector *connector); int intel_hdcp_disable(struct intel_connector *connector); int intel_hdcp_check_link(struct intel_connector *connector); +bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); /* intel_psr.c */ void intel_psr_enable(struct intel_dp *intel_dp, -- cgit v1.1 From 791a98dd9bcfd214d8ef51d248f377354a9ea683 Mon Sep 17 00:00:00 2001 From: Ramalingam C Date: Sat, 3 Feb 2018 03:39:08 +0530 Subject: drm/i915: Detect panel's hdcp capability DP HDCP1.4 spec mandates that An can be written to panel only after detecting the panel's hdcp capability. For DP 0th Bit of Bcaps register indicates the panel's hdcp capability For HDMI valid BKSV indicates the panel's hdcp capability. For HDMI it is optional to detect the panel's hdcp capability before An Write. v2: Added comments explaining the need for action [Seanpaul]. Made panel's hdcp capability detection optional for hdmi [Seanpaul]. Defined a func for reading bcaps for DP [Seanpaul]. v3: Removed the NULL initialization [Seanpaul]. Signed-off-by: Ramalingam C Reviewed-by: Sean Paul Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/1517609350-10698-7-git-send-email-ramalingam.c@intel.com --- drivers/gpu/drm/i915/intel_drv.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915/intel_drv.h') diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9461777..c902be8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -369,6 +369,10 @@ struct intel_hdcp_shim { /* Ensures the link is still protected */ bool (*check_link)(struct intel_digital_port *intel_dig_port); + + /* Detects panel's hdcp capability. This is optional for HDMI. */ + int (*hdcp_capable)(struct intel_digital_port *intel_dig_port, + bool *hdcp_capable); }; struct intel_connector { -- cgit v1.1