[Intel-gfx] [PATCH v10 09/10] arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
From: Sean Paul Add the register ranges required for HDCP key injection and HDCP TrustZone interaction as described in the dt-bindings for the sc7180 dp controller. Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v3: -Split off into a new patch containing just the dts change (Stephen) -Add hdcp compatible string (Stephen) Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Put the tz register offsets in trogdor dtsi (Rob C) Changes in v6: -Rebased: Removed modifications in sc7180.dtsi as it's already upstream Changes in v7: -Change registers offset arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index 423630c4d02c7..89d913fa6e3eb 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -822,6 +822,14 @@ &mdss_dp { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hot_plug_det>; + + reg = <0 0x0ae9 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; }; &mdss_dp_out { -- 2.40.0.634.g4ca3ef3211-goog
[Intel-gfx] [PATCH v10 10/10] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul Add HDCP 1.x support to msm DP bridges using the new HDCP helpers. Cc: Stephen Boyd Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) Changes in v3: -Split out the dtsi change from v2 (Stephen) -Fix set-but-unused warning identified by 0-day -Fix up a couple of style nits (Stephen) -Store HDCP key directly in dp_hdcp struct (Stephen) -Remove wmb in HDCP key initialization, move an_seed (Stephen) -Use FIELD_PREP for bstatus/bcaps (Stephen) -#define read_poll_timeout values (Stephen) -Remove unnecessary parentheses in dp_hdcp_store_ksv_fifo (Stephen) -Add compatible string for hdcp (Stephen) -Rename dp_hdcp_write_* functions (Abhinav) -Add 1us delay between An reads (Abhinav) -Delete unused dp_hdcp_read_* functions Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Change return check of drm_hdcp_helper_initialize_dp() (Stephen) Changes in v6: -Change the tracking of the state from connector state to bridge as state as drm_connector_state is no longer tracked and the functionality has moved to msm_dp_bridge Changes in v7: -Use dp bridge to maintain the state with no use for connector Changes in v8: -Move the hdcp read/write to dp_catalog Changes in v9: -Remove display type specific helper funcs init from driver Changes in v10: -Fix #include to include directory (kernel test bot) drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 +++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 ++ drivers/gpu/drm/msm/dp/dp_debug.c | 46 +++- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 7 + drivers/gpu/drm/msm/dp/dp_hdcp.c| 389 drivers/gpu/drm/msm/dp/dp_hdcp.h| 33 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 14 + drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 ++- drivers/gpu/drm/msm/msm_atomic.c| 19 ++ 16 files changed, 800 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 4d8fddbdcd9e0..1c369ca2ea6e3 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,6 +15,7 @@ config DRM_MSM select REGULATOR select DRM_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7274c41228ed9..a73e7b858af27 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -122,6 +122,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 676279d0ca8d9..a1395e0c67d56 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -16,6 +16,8 @@ #include "dp_catalog.h" #include "dp_reg.h" +#include + #define POLLING_SLEEP_US 1000 #define POLLING_TIMEOUT_US 1 @@ -47,6 +49,14 @@ #define DP_INTERRUPT_STATUS2_MASK \ (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) +#define DP_AN_READ_DELAY_US 1 +/* Key offsets based on hdcp_key mmio */ +#define DP_HDCP_KEY_BASE 0x30 +#define DP_HDCP_KEY_MSB(x) (DP_HDCP_KEY_BASE + (x * 8)) +#define DP_HDCP_KEY_LSB(x) (DP_HDCP_KEY_MSB(x) + 4) +#define DP_HDCP_KEY_VALID 0x170 +#define DP_HDCP_SW_KEY_VALID BIT(0) + struct dp_catalog_private { struct device *dev; struct drm_device *drm_dev; @@ -133,6 +143,18 @@ static inline void dp_write_link(struct dp_catalog_private *catalog, writel(data, catalog->io->dp_controller.link.base + offset); } +static inline void dp_write_hdcp_key(struct dp_catalog_private *catalog, +u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_key.base + offset); +} + +static inline void dp_write_hdcp_tz(struct dp_catalog_private *catalog, + u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_tz.base + offset); +} + /* aux related catalog functions */ u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) { @@ -1094,3 +1116,137 @@ void dp_catal
[Intel-gfx] [PATCH v10 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: - None drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000aa..0a20bc41be55d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.40.0.634.g4ca3ef3211-goog
[Intel-gfx] [PATCH v10 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Acked-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. Changes in v7: -Added to drm_hdcp_helper_funcs new functions that are unique between DP and HDMI -Adjusted the function signatures to take "driver data" Changes in v8: -None Changes in v9: -rename dev_priv to i915 -remove display type specific hdcp calls init from driver Changes in v10: -Make functions static (kernel bot warning) drivers/gpu/drm/display/drm_hdcp_helper.c | 12 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 7 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 352 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 984 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 43 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 267 ++--- 9 files changed, 481 insertions(+), 1283 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 9b62e476d21b4..41f5619dfd258 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -672,8 +672,8 @@ static int drm_hdcp_read_valid_bksv(struct drm_hdcp_helper_data *data, return 0; } -int drm_hdcp_helper_hdcp1_capable_dp(struct drm_hdcp_helper_data *data, -bool *capable) +static int drm_hdcp_helper_hdcp1_capable_dp(struct drm_hdcp_helper_data *data, + bool *capable) { int ret; u8 bcaps; @@ -1322,9 +1322,10 @@ static void drm_hdcp_helper_prop_work(struct work_struct *work) /* * Check the link registers for HDCP 1.x for DP. */ -int drm_hdcp_hdcp1_check_link_registers_dp(struct drm_device *dev, - struct drm_hdcp_helper_data *data, - bool *shoud_retry) +static int +drm_hdcp_hdcp1_check_link_registers_dp(struct drm_device *dev, + struct drm_hdcp_helper_data *data, + bool *shoud_retry) { u8 bstatus; int ret = drm_hdcp_remote_dpcd_read(data, DP_AUX_HDCP_BSTATUS, &bstatus, @@ -1341,7 +1342,6 @@ int drm_hdcp_hdcp1_check_link_registers_dp(struct drm_device *dev, return 0; } -EXPORT_SYMBOL(drm_hdcp_hdcp1_check_link_registers_dp); static int drm_hdcp_hdcp1_check_link_registers_hdmi(struct drm_device *dev, diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 254559abedfba..8a2f20c929e9c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2956,6 +2957,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2975,12 +2980,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->hd
[Intel-gfx] [PATCH v10 08/10] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul Add the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. Cc: Rob Herring Cc: Stephen Boyd Reviewed-by: Rob Herring Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Drop register range names (Stephen) -Fix yaml errors (Rob) Changes in v3: -Add new compatible string for dp-hdcp -Add descriptions to reg -Add minItems/maxItems to reg -Make reg depend on the new hdcp compatible string Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v4.5: -Remove maxItems from reg (Rob) -Remove leading zeros in example (Rob) Changes in v5: -None Changes in v6: -Rebased: modify minItems instead of adding it as new line. Changes in v7: -Revert the change to minItems -Added the maxItems to Reg .../devicetree/bindings/display/msm/dp-controller.yaml | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 0e8d8df686dc9..4763a2ff12fb7 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -34,6 +34,8 @@ properties: - description: link register block - description: p0 register block - description: p1 register block + - description: (Optional) Registers for HDCP device key injection + - description: (Optional) Registers for HDCP TrustZone interaction interrupts: maxItems: 1 @@ -159,6 +161,7 @@ allOf: aux-bus: false reg: minItems: 5 + maxItems: 7 required: - "#sound-dai-cells" @@ -176,7 +179,9 @@ examples: <0xae90200 0x200>, <0xae90400 0xc00>, <0xae91000 0x400>, - <0xae91400 0x400>; + <0xae91400 0x400>, + <0xaed1000 0x174>, + <0xaee1000 0x2c>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.40.0.634.g4ca3ef3211-goog
[Intel-gfx] [PATCH v10 04/10] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul Expand upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the shim vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Acked-by: Jani Nikula Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Fixed typo in function descriptions -Rebased: Moved the new code between drm_hdcp.h and drm_hdcp_helper.c/h -Add missing headers. Reported-by: kernel test robot Changes in v7: - Add a |driver_data| field to some functions in drm_hdcp_helper_funcs that are called by the driver so drivers can pass anything they such as bridges - Isolate all non-common code between HDMI and DP into separate functions instead of manually checking for datra->aux Changes in v8 (suraj): -Try hdcp 1.x if hdcp2_capable returns an error instead of goto out. -set the enabled type to either 1 or 0 depending on the prop as hdcp2 can support either. Changes in v9: -Replace the drm_err by drm_dbg_kms -Assign data->enabled_type without if-statement -Moved display type specific func init into the drm helper drivers/gpu/drm/display/drm_hdcp_helper.c | 1136 + include/drm/display/drm_hdcp.h| 296 ++ include/drm/display/drm_hdcp_helper.h | 22 +- 3 files changed, 1453 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 3ee1a6ae26c53..9b62e476d21b4 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -6,13 +6,18 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -507,3 +512,1134 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register +* definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +
[Intel-gfx] [PATCH v10 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Suraj Kandpal Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased Changes in v7: -None .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7bcd90384a46d..a14b86a07e545 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -494,6 +494,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -501,8 +502,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55d..61a862ae1f286 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2373,21 +2373,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if
[Intel-gfx] [PATCH v10 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, rename to drm_hdcp_has_changed and return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Renamed the function from drm_hdcp_atomic_check to drm_hdcp_has_changed (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 39 ++--- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7ca390b3ea106..34baf2b97cd87 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -422,18 +422,21 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, EXPORT_SYMBOL(drm_hdcp_update_content_protection); /** - * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * drm_hdcp_has_changed - Helper for drivers to call during connector->atomic_check * * @state: pointer to the atomic state being checked * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) +bool drm_hdcp_has_changed(struct drm_connector *connector, + struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; struct drm_crtc_state *new_crtc_state; @@ -450,19 +453,31 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from UNDESIRED state, CRTC change or re-enablement requires +* the driver to try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -477,9 +492,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } -EXPORT_SYMBOL(drm_hdcp_atomic_check); +EXPORT_SYMBOL(drm_hdcp_has_changed); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index e9d00b6a63d39..23a6ba315a22e 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -124,8 +124,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdc
[Intel-gfx] [PATCH v10 03/10] drm/hdcp: Update property value on content type and user changes
From: Sean Paul Update the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Rebased as function name has changed. drivers/gpu/drm/display/drm_hdcp_helper.c | 29 +++ 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 34baf2b97cd87..3ee1a6ae26c53 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -480,21 +480,30 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change -* - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* Content type changes require an HDCP disable/enable cycle. */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if (new_conn_state->hdcp_content_type != + old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: +* - HDCP was activated since the last commit +* - Attempting to set to desired while already enabled +*/ + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); -- 2.40.0.634.g4ca3ef3211-goog
[Intel-gfx] [PATCH v10 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul Move the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Dmitry Baryshkov Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c Changes in v7: -Removed links to patch from commit msg (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 64 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 --- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd77..7ca390b3ea106 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,66 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index a9a3f3715279d..e9d00b6a63d39 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -39,7 +40,6 @@ #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "intel_fb.h" #include "skl_universal_plane.h" @@ -124,7 +124,7 @@ int intel_digital_connector_atomic_check(s
[Intel-gfx] [PATCH v10 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers
Hi all, This is v10 of the HDCP patches. The patches are authored by Sean Paul. I rebased and addressed the review comments in v6-v10. Main change in v10 is handling the kernel test bot warnings. Patches 1-4 focus on moving the common HDCP helpers to common DRM. This introduces a slight change in the original intel flow as it splits the unique driver protocol from the generic implementation. Patches 5-7 split the HDCP flow on the i915 driver to make use of the common DRM helpers. Patches 8-10 implement HDCP on MSM driver. Thanks, -Mark Yacoub Sean Paul (10): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 dt-bindings: msm/dp: Add bindings for HDCP registers arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |7 +- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi |8 + drivers/gpu/drm/display/drm_hdcp_helper.c | 1224 + drivers/gpu/drm/i915/display/intel_atomic.c |8 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 12 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 352 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1060 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 48 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 267 ++-- drivers/gpu/drm/msm/Kconfig |1 + drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 +++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 + drivers/gpu/drm/msm/dp/dp_debug.c | 46 +- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 +- drivers/gpu/drm/msm/dp/dp_drm.h |7 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 389 ++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 33 + drivers/gpu/drm/msm/dp/dp_parser.c| 14 + drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 +- drivers/gpu/drm/msm/msm_atomic.c | 19 + include/drm/display/drm_hdcp.h| 296 include/drm/display/drm_hdcp_helper.h | 23 + 30 files changed, 2867 insertions(+), 1349 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- 2.40.0.634.g4ca3ef3211-goog
[Intel-gfx] [PATCH v9 10/10] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul Add HDCP 1.x support to msm DP bridges using the new HDCP helpers. Cc: Stephen Boyd Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) Changes in v3: -Split out the dtsi change from v2 (Stephen) -Fix set-but-unused warning identified by 0-day -Fix up a couple of style nits (Stephen) -Store HDCP key directly in dp_hdcp struct (Stephen) -Remove wmb in HDCP key initialization, move an_seed (Stephen) -Use FIELD_PREP for bstatus/bcaps (Stephen) -#define read_poll_timeout values (Stephen) -Remove unnecessary parentheses in dp_hdcp_store_ksv_fifo (Stephen) -Add compatible string for hdcp (Stephen) -Rename dp_hdcp_write_* functions (Abhinav) -Add 1us delay between An reads (Abhinav) -Delete unused dp_hdcp_read_* functions Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Change return check of drm_hdcp_helper_initialize_dp() (Stephen) Changes in v6: -Change the tracking of the state from connector state to bridge as state as drm_connector_state is no longer tracked and the functionality has moved to msm_dp_bridge Changes in v7: -Use dp bridge to maintain the state with no use for connector Changes in v8: -Move the hdcp read/write to dp_catalog Changes in v9: -Remove display type specific helper funcs init from driver drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 +++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 ++ drivers/gpu/drm/msm/dp/dp_debug.c | 46 +++- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 7 + drivers/gpu/drm/msm/dp/dp_hdcp.c| 389 drivers/gpu/drm/msm/dp/dp_hdcp.h| 33 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 14 + drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 ++- drivers/gpu/drm/msm/msm_atomic.c| 19 ++ 16 files changed, 800 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 4d8fddbdcd9e0..1c369ca2ea6e3 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,6 +15,7 @@ config DRM_MSM select REGULATOR select DRM_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7274c41228ed9..a73e7b858af27 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -122,6 +122,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 676279d0ca8d9..a1395e0c67d56 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -16,6 +16,8 @@ #include "dp_catalog.h" #include "dp_reg.h" +#include + #define POLLING_SLEEP_US 1000 #define POLLING_TIMEOUT_US 1 @@ -47,6 +49,14 @@ #define DP_INTERRUPT_STATUS2_MASK \ (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) +#define DP_AN_READ_DELAY_US 1 +/* Key offsets based on hdcp_key mmio */ +#define DP_HDCP_KEY_BASE 0x30 +#define DP_HDCP_KEY_MSB(x) (DP_HDCP_KEY_BASE + (x * 8)) +#define DP_HDCP_KEY_LSB(x) (DP_HDCP_KEY_MSB(x) + 4) +#define DP_HDCP_KEY_VALID 0x170 +#define DP_HDCP_SW_KEY_VALID BIT(0) + struct dp_catalog_private { struct device *dev; struct drm_device *drm_dev; @@ -133,6 +143,18 @@ static inline void dp_write_link(struct dp_catalog_private *catalog, writel(data, catalog->io->dp_controller.link.base + offset); } +static inline void dp_write_hdcp_key(struct dp_catalog_private *catalog, +u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_key.base + offset); +} + +static inline void dp_write_hdcp_tz(struct dp_catalog_private *catalog, + u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_tz.base + offset); +} + /* aux related catalog functions */ u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) { @@ -1094,3 +1116,137 @@ void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) dp_write_link
[Intel-gfx] [PATCH v9 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Acked-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. Changes in v7: -Added to drm_hdcp_helper_funcs new functions that are unique between DP and HDMI -Adjusted the function signatures to take "driver data" Changes in v8: -None Changes in v9: -rename dev_priv to i915 -remove display type specific hdcp calls init from driver drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 7 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 352 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 984 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 43 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 267 ++--- 8 files changed, 475 insertions(+), 1277 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 254559abedfba..8a2f20c929e9c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2956,6 +2957,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2975,12 +2980,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, @@ -3026,7 +3029,14 @@ 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, @@ -3054,13 +3064,19 @@ 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);
[Intel-gfx] [PATCH v9 09/10] arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
From: Sean Paul Add the register ranges required for HDCP key injection and HDCP TrustZone interaction as described in the dt-bindings for the sc7180 dp controller. Reviewed-by: Dmitry Baryshkov Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v3: -Split off into a new patch containing just the dts change (Stephen) -Add hdcp compatible string (Stephen) Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Put the tz register offsets in trogdor dtsi (Rob C) Changes in v6: -Rebased: Removed modifications in sc7180.dtsi as it's already upstream Changes in v7: -Change registers offset arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index 423630c4d02c7..89d913fa6e3eb 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -822,6 +822,14 @@ &mdss_dp { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hot_plug_det>; + + reg = <0 0x0ae9 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; }; &mdss_dp_out { -- 2.40.0.577.gac1e443424-goog
[Intel-gfx] [PATCH v9 08/10] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul Add the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. Cc: Rob Herring Cc: Stephen Boyd Reviewed-by: Rob Herring Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Drop register range names (Stephen) -Fix yaml errors (Rob) Changes in v3: -Add new compatible string for dp-hdcp -Add descriptions to reg -Add minItems/maxItems to reg -Make reg depend on the new hdcp compatible string Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v4.5: -Remove maxItems from reg (Rob) -Remove leading zeros in example (Rob) Changes in v5: -None Changes in v6: -Rebased: modify minItems instead of adding it as new line. Changes in v7: -Revert the change to minItems -Added the maxItems to Reg .../devicetree/bindings/display/msm/dp-controller.yaml | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 0e8d8df686dc9..4763a2ff12fb7 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -34,6 +34,8 @@ properties: - description: link register block - description: p0 register block - description: p1 register block + - description: (Optional) Registers for HDCP device key injection + - description: (Optional) Registers for HDCP TrustZone interaction interrupts: maxItems: 1 @@ -159,6 +161,7 @@ allOf: aux-bus: false reg: minItems: 5 + maxItems: 7 required: - "#sound-dai-cells" @@ -176,7 +179,9 @@ examples: <0xae90200 0x200>, <0xae90400 0xc00>, <0xae91000 0x400>, - <0xae91400 0x400>; + <0xae91400 0x400>, + <0xaed1000 0x174>, + <0xaee1000 0x2c>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.40.0.577.gac1e443424-goog
[Intel-gfx] [PATCH v9 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Suraj Kandpal Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased Changes in v7: -None .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7bcd90384a46d..a14b86a07e545 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -494,6 +494,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -501,8 +502,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55d..61a862ae1f286 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2373,21 +2373,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if
[Intel-gfx] [PATCH v9 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: - None drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000aa..0a20bc41be55d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.40.0.577.gac1e443424-goog
[Intel-gfx] [PATCH v9 04/10] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul Expand upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the shim vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Acked-by: Jani Nikula Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Fixed typo in function descriptions -Rebased: Moved the new code between drm_hdcp.h and drm_hdcp_helper.c/h -Add missing headers. Reported-by: kernel test robot Changes in v7: - Add a |driver_data| field to some functions in drm_hdcp_helper_funcs that are called by the driver so drivers can pass anything they such as bridges - Isolate all non-common code between HDMI and DP into separate functions instead of manually checking for datra->aux Changes in v8 (suraj): -Try hdcp 1.x if hdcp2_capable returns an error instead of goto out. -set the enabled type to either 1 or 0 depending on the prop as hdcp2 can support either. Changes in v9: -Replace the drm_err by drm_dbg_kms -Assign data->enabled_type without if-statement -Moved display type specific func init into the drm helper drivers/gpu/drm/display/drm_hdcp_helper.c | 1136 + include/drm/display/drm_hdcp.h| 296 ++ include/drm/display/drm_hdcp_helper.h | 22 +- 3 files changed, 1453 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 3ee1a6ae26c53..9b62e476d21b4 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -6,13 +6,18 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -507,3 +512,1134 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register +* definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +
[Intel-gfx] [PATCH v9 03/10] drm/hdcp: Update property value on content type and user changes
From: Sean Paul Update the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Rebased as function name has changed. drivers/gpu/drm/display/drm_hdcp_helper.c | 29 +++ 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 34baf2b97cd87..3ee1a6ae26c53 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -480,21 +480,30 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change -* - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* Content type changes require an HDCP disable/enable cycle. */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if (new_conn_state->hdcp_content_type != + old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: +* - HDCP was activated since the last commit +* - Attempting to set to desired while already enabled +*/ + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); -- 2.40.0.577.gac1e443424-goog
[Intel-gfx] [PATCH v9 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, rename to drm_hdcp_has_changed and return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Renamed the function from drm_hdcp_atomic_check to drm_hdcp_has_changed (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 39 ++--- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7ca390b3ea106..34baf2b97cd87 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -422,18 +422,21 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, EXPORT_SYMBOL(drm_hdcp_update_content_protection); /** - * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * drm_hdcp_has_changed - Helper for drivers to call during connector->atomic_check * * @state: pointer to the atomic state being checked * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) +bool drm_hdcp_has_changed(struct drm_connector *connector, + struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; struct drm_crtc_state *new_crtc_state; @@ -450,19 +453,31 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from UNDESIRED state, CRTC change or re-enablement requires +* the driver to try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -477,9 +492,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } -EXPORT_SYMBOL(drm_hdcp_atomic_check); +EXPORT_SYMBOL(drm_hdcp_has_changed); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index e9d00b6a63d39..23a6ba315a22e 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -124,8 +124,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdc
[Intel-gfx] [PATCH v9 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul Move the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Dmitry Baryshkov Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c Changes in v7: -Removed links to patch from commit msg (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 64 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 --- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd77..7ca390b3ea106 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,66 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index a9a3f3715279d..e9d00b6a63d39 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -39,7 +40,6 @@ #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "intel_fb.h" #include "skl_universal_plane.h" @@ -124,7 +124,7 @@ int intel_digital_connector_atomic_check(s
[Intel-gfx] [PATCH v9 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers
Hi all, This is v7 of the HDCP patches. The patches are authored by Sean Paul. I rebased and addressed the review comments in v6-v9. Main change in v9 is renaming i915 priv data and moving the display type specific init to the drm helper instead of the driver. Patches 1-4 focus on moving the common HDCP helpers to common DRM. This introduces a slight change in the original intel flow as it splits the unique driver protocol from the generic implementation. Patches 5-7 split the HDCP flow on the i915 driver to make use of the common DRM helpers. Patches 8-10 implement HDCP on MSM driver. Thanks, -Mark Yacoub Sean Paul (10): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 dt-bindings: msm/dp: Add bindings for HDCP registers arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |7 +- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi |8 + drivers/gpu/drm/display/drm_hdcp_helper.c | 1224 + drivers/gpu/drm/i915/display/intel_atomic.c |8 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 12 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 352 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1060 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 48 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 267 ++-- drivers/gpu/drm/msm/Kconfig |1 + drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 +++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 + drivers/gpu/drm/msm/dp/dp_debug.c | 46 +- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 +- drivers/gpu/drm/msm/dp/dp_drm.h |7 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 389 ++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 33 + drivers/gpu/drm/msm/dp/dp_parser.c| 14 + drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 +- drivers/gpu/drm/msm/msm_atomic.c | 19 + include/drm/display/drm_hdcp.h| 296 include/drm/display/drm_hdcp_helper.h | 23 + 30 files changed, 2867 insertions(+), 1349 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- 2.40.0.577.gac1e443424-goog
[Intel-gfx] [PATCH v8 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, rename to drm_hdcp_has_changed and return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Renamed the function from drm_hdcp_atomic_check to drm_hdcp_has_changed (Dmitry Baryshkov) Changes in v8: -None drivers/gpu/drm/display/drm_hdcp_helper.c | 39 ++--- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7ca390b3ea106..34baf2b97cd87 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -422,18 +422,21 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, EXPORT_SYMBOL(drm_hdcp_update_content_protection); /** - * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * drm_hdcp_has_changed - Helper for drivers to call during connector->atomic_check * * @state: pointer to the atomic state being checked * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) +bool drm_hdcp_has_changed(struct drm_connector *connector, + struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; struct drm_crtc_state *new_crtc_state; @@ -450,19 +453,31 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from UNDESIRED state, CRTC change or re-enablement requires +* the driver to try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -477,9 +492,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } -EXPORT_SYMBOL(drm_hdcp_atomic_check); +EXPORT_SYMBOL(drm_hdcp_has_changed); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index e9d00b6a63d39..23a6ba315a22e 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -124,8 +124,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - d
[Intel-gfx] [PATCH v8 09/10] arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
From: Sean Paul Add the register ranges required for HDCP key injection and HDCP TrustZone interaction as described in the dt-bindings for the sc7180 dp controller. Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v3: -Split off into a new patch containing just the dts change (Stephen) -Add hdcp compatible string (Stephen) Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Put the tz register offsets in trogdor dtsi (Rob C) Changes in v6: -Rebased: Removed modifications in sc7180.dtsi as it's already upstream Changes in v7: -Change registers offset Changes in v8: -None arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index 423630c4d02c7..89d913fa6e3eb 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -822,6 +822,14 @@ &mdss_dp { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hot_plug_det>; + + reg = <0 0x0ae9 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; }; &mdss_dp_out { -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v8 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Change-Id: Ib358a503fa4520d072e477f708f1705b19f1c4fc Signed-off-by: Sean Paul --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: - None Changes in v8: -None drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000aa..0a20bc41be55d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v8 10/10] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul Add HDCP 1.x support to msm DP bridges using the new HDCP helpers. Cc: Stephen Boyd Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) Changes in v3: -Split out the dtsi change from v2 (Stephen) -Fix set-but-unused warning identified by 0-day -Fix up a couple of style nits (Stephen) -Store HDCP key directly in dp_hdcp struct (Stephen) -Remove wmb in HDCP key initialization, move an_seed (Stephen) -Use FIELD_PREP for bstatus/bcaps (Stephen) -#define read_poll_timeout values (Stephen) -Remove unnecessary parentheses in dp_hdcp_store_ksv_fifo (Stephen) -Add compatible string for hdcp (Stephen) -Rename dp_hdcp_write_* functions (Abhinav) -Add 1us delay between An reads (Abhinav) -Delete unused dp_hdcp_read_* functions Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Change return check of drm_hdcp_helper_initialize_dp() (Stephen) Changes in v6: -Change the tracking of the state from connector state to bridge as state as drm_connector_state is no longer tracked and the functionality has moved to msm_dp_bridge Changes in v7: -Use dp bridge to maintain the state with no use for connector Changes in v8: -Move the hdcp read/write to dp_catalog drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 +++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 ++ drivers/gpu/drm/msm/dp/dp_debug.c | 46 +++- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 7 + drivers/gpu/drm/msm/dp/dp_hdcp.c| 397 drivers/gpu/drm/msm/dp/dp_hdcp.h| 33 +++ drivers/gpu/drm/msm/dp/dp_parser.c | 14 + drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 ++- drivers/gpu/drm/msm/msm_atomic.c| 19 ++ 16 files changed, 808 insertions(+), 12 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 4d8fddbdcd9e0..1c369ca2ea6e3 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,6 +15,7 @@ config DRM_MSM select REGULATOR select DRM_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7274c41228ed9..a73e7b858af27 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -122,6 +122,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index 676279d0ca8d9..a1395e0c67d56 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -16,6 +16,8 @@ #include "dp_catalog.h" #include "dp_reg.h" +#include + #define POLLING_SLEEP_US 1000 #define POLLING_TIMEOUT_US 1 @@ -47,6 +49,14 @@ #define DP_INTERRUPT_STATUS2_MASK \ (DP_INTERRUPT_STATUS2 << DP_INTERRUPT_STATUS_MASK_SHIFT) +#define DP_AN_READ_DELAY_US 1 +/* Key offsets based on hdcp_key mmio */ +#define DP_HDCP_KEY_BASE 0x30 +#define DP_HDCP_KEY_MSB(x) (DP_HDCP_KEY_BASE + (x * 8)) +#define DP_HDCP_KEY_LSB(x) (DP_HDCP_KEY_MSB(x) + 4) +#define DP_HDCP_KEY_VALID 0x170 +#define DP_HDCP_SW_KEY_VALID BIT(0) + struct dp_catalog_private { struct device *dev; struct drm_device *drm_dev; @@ -133,6 +143,18 @@ static inline void dp_write_link(struct dp_catalog_private *catalog, writel(data, catalog->io->dp_controller.link.base + offset); } +static inline void dp_write_hdcp_key(struct dp_catalog_private *catalog, +u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_key.base + offset); +} + +static inline void dp_write_hdcp_tz(struct dp_catalog_private *catalog, + u32 offset, u32 val) +{ + writel(val, catalog->io->dp_controller.hdcp_tz.base + offset); +} + /* aux related catalog functions */ u32 dp_catalog_aux_read_data(struct dp_catalog *dp_catalog) { @@ -1094,3 +1116,137 @@ void dp_catalog_audio_sfe_level(struct dp_catalog *dp_catalog) dp_write_link(catalog, REG_DP_MAINLINK_LEVELS, mainlink_levels); } + +u32 dp_catalog
[Intel-gfx] [PATCH v8 04/10] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul Expand upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the shim vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Acked-by: Jani Nikula Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Fixed typo in function descriptions -Rebased: Moved the new code between drm_hdcp.h and drm_hdcp_helper.c/h -Add missing headers. Reported-by: kernel test robot Changes in v7: - Add a |driver_data| field to some functions in drm_hdcp_helper_funcs that are called by the driver so drivers can pass anything they such as bridges - Isolate all non-common code between HDMI and DP into separate functions instead of manually checking for datra->aux Changes in v8 (suraj): -Try hdcp 1.x if hdcp2_capable returns an error instead of goto out. -set the enabled type to either 1 or 0 depending on the prop as hdcp2 can support either. drivers/gpu/drm/display/drm_hdcp_helper.c | 1215 + include/drm/display/drm_hdcp.h| 287 + include/drm/display/drm_hdcp_helper.h | 51 +- 3 files changed, 1552 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 3ee1a6ae26c53..3bc0308cc95d8 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -6,13 +6,18 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -507,3 +512,1213 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register +* definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +*/ + .bstatus = DP_AUX_HDCP_BINFO, +}; + +/* + * Read a DPCD register. + * + * @data: drm_hdcp_helper_data containing the DisplayPort AUX channel (SST or MST)
[Intel-gfx] [PATCH v8 08/10] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul Add the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. Cc: Rob Herring Cc: Stephen Boyd Reviewed-by: Rob Herring Reviewed-by: Douglas Anderson Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Drop register range names (Stephen) -Fix yaml errors (Rob) Changes in v3: -Add new compatible string for dp-hdcp -Add descriptions to reg -Add minItems/maxItems to reg -Make reg depend on the new hdcp compatible string Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v4.5: -Remove maxItems from reg (Rob) -Remove leading zeros in example (Rob) Changes in v5: -None Changes in v6: -Rebased: modify minItems instead of adding it as new line. Changes in v7: -Revert the change to minItems -Added the maxItems to Reg Changes in v8: -None .../devicetree/bindings/display/msm/dp-controller.yaml | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 0e8d8df686dc9..4763a2ff12fb7 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -34,6 +34,8 @@ properties: - description: link register block - description: p0 register block - description: p1 register block + - description: (Optional) Registers for HDCP device key injection + - description: (Optional) Registers for HDCP TrustZone interaction interrupts: maxItems: 1 @@ -159,6 +161,7 @@ allOf: aux-bus: false reg: minItems: 5 + maxItems: 7 required: - "#sound-dai-cells" @@ -176,7 +179,9 @@ examples: <0xae90200 0x200>, <0xae90400 0xc00>, <0xae91000 0x400>, - <0xae91400 0x400>; + <0xae91400 0x400>, + <0xaed1000 0x174>, + <0xaee1000 0x2c>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v8 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased Changes in v7: -None Changes in v8: -None .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7bcd90384a46d..a14b86a07e545 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -494,6 +494,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -501,8 +502,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55d..61a862ae1f286 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2373,21 +2373,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if
[Intel-gfx] [PATCH v8 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Acked-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. Changes in v7: -Added to drm_hdcp_helper_funcs new functions that are unique between DP and HDMI -Adjusted the function signatures to take "driver data" Changes in v8: -None drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 6 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 368 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 960 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 37 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 276 ++--- 8 files changed, 484 insertions(+), 1262 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 254559abedfba..8a2f20c929e9c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2956,6 +2957,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2975,12 +2980,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, @@ -3026,7 +3029,14 @@ 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, @@ -3054,13 +3064,19 @@ 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-gfx] [PATCH v8 03/10] drm/hdcp: Update property value on content type and user changes
From: Sean Paul Update the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Rebased as function name has changed. Changes in v8: -None drivers/gpu/drm/display/drm_hdcp_helper.c | 29 +++ 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 34baf2b97cd87..3ee1a6ae26c53 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -480,21 +480,30 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change -* - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* Content type changes require an HDCP disable/enable cycle. */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if (new_conn_state->hdcp_content_type != + old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: +* - HDCP was activated since the last commit +* - Attempting to set to desired while already enabled +*/ + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v8 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul Move the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Dmitry Baryshkov Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c Changes in v7: -Removed links to patch from commit msg (Dmitry Baryshkov) Changes in v8: -None drivers/gpu/drm/display/drm_hdcp_helper.c | 64 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 --- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd77..7ca390b3ea106 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,66 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index a9a3f3715279d..e9d00b6a63d39 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -39,7 +40,6 @@ #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "intel_fb.h" #include "skl_universal_plane.h" @@ -124,7 +124,7 @@ int int
[Intel-gfx] [PATCH v8 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers
Hi all, This is v7 of the HDCP patches. The patches are authored by Sean Paul. I rebased and addressed the review comments in v6-v8. Patches 1-4 focus on moving the common HDCP helpers to common DRM. This introduces a slight change in the original intel flow as it splits the unique driver protocol from the generic implementation. Patches 5-7 split the HDCP flow on the i915 driver to make use of the common DRM helpers. Patches 8-10 implement HDCP on MSM driver. Thanks, -Mark Yacoub Sean Paul (10): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 dt-bindings: msm/dp: Add bindings for HDCP registers arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |7 +- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi |8 + drivers/gpu/drm/display/drm_hdcp_helper.c | 1303 + drivers/gpu/drm/i915/display/intel_atomic.c |8 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 11 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 368 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1036 +++-- drivers/gpu/drm/i915/display/intel_hdcp.h | 42 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 276 ++-- drivers/gpu/drm/msm/Kconfig |1 + drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/dp/dp_catalog.c | 156 ++ drivers/gpu/drm/msm/dp/dp_catalog.h | 18 + drivers/gpu/drm/msm/dp/dp_debug.c | 46 +- drivers/gpu/drm/msm/dp/dp_debug.h | 11 +- drivers/gpu/drm/msm/dp/dp_display.c | 39 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 +- drivers/gpu/drm/msm/dp/dp_drm.h |7 + drivers/gpu/drm/msm/dp/dp_hdcp.c | 397 + drivers/gpu/drm/msm/dp/dp_hdcp.h | 33 + drivers/gpu/drm/msm/dp/dp_parser.c| 14 + drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 +- drivers/gpu/drm/msm/msm_atomic.c | 19 + include/drm/display/drm_hdcp.h| 287 include/drm/display/drm_hdcp_helper.h | 52 + 30 files changed, 2983 insertions(+), 1334 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Acked-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. Changes in v7: -Added to drm_hdcp_helper_funcs new functions that are unique between DP and HDMI -Adjusted the function signatures to take "driver data" drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 6 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 368 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 960 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 37 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 276 ++--- 8 files changed, 484 insertions(+), 1262 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0f1ec2a98cc87..550a99d1811b4 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2941,6 +2942,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2957,12 +2962,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, @@ -3008,7 +3011,14 @@ 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, @@ -3036,13 +3046,19 @@ 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-gfx] [PATCH v7 10/10] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul Add HDCP 1.x support to msm DP bridges using the new HDCP helpers. Cc: Stephen Boyd Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) Changes in v3: -Split out the dtsi change from v2 (Stephen) -Fix set-but-unused warning identified by 0-day -Fix up a couple of style nits (Stephen) -Store HDCP key directly in dp_hdcp struct (Stephen) -Remove wmb in HDCP key initialization, move an_seed (Stephen) -Use FIELD_PREP for bstatus/bcaps (Stephen) -#define read_poll_timeout values (Stephen) -Remove unnecessary parentheses in dp_hdcp_store_ksv_fifo (Stephen) -Add compatible string for hdcp (Stephen) -Rename dp_hdcp_write_* functions (Abhinav) -Add 1us delay between An reads (Abhinav) -Delete unused dp_hdcp_read_* functions Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Change return check of drm_hdcp_helper_initialize_dp() (Stephen) Changes in v6: -Change the tracking of the state from connector state to bridge as state as drm_connector_state is no longer tracked and the functionality has moved to msm_dp_bridge Changes in v7: -Use dp bridge to maintain the state with no use for connector drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_debug.c | 48 ++- drivers/gpu/drm/msm/dp/dp_debug.h | 17 +- drivers/gpu/drm/msm/dp/dp_display.c | 42 ++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 12 +- drivers/gpu/drm/msm/dp/dp_hdcp.c| 483 drivers/gpu/drm/msm/dp/dp_hdcp.h| 31 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 19 ++ drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 +- drivers/gpu/drm/msm/msm_atomic.c| 19 ++ 14 files changed, 732 insertions(+), 19 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 86f0e64cbda30..c3e4d6102a5fa 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,6 +15,7 @@ config DRM_MSM select REGULATOR select DRM_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7274c41228ed9..a73e7b858af27 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -122,6 +122,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 5e35033ba3e43..e97d27edbb13b 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "dp_parser.h" #include "dp_catalog.h" @@ -15,6 +16,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "dp_display.h" +#include "dp_hdcp.h" #define DEBUG_NAME "msm_dp" @@ -25,6 +27,7 @@ struct dp_debug_private { struct dp_link *link; struct dp_panel *panel; struct drm_connector *connector; + struct dp_hdcp *hdcp; struct device *dev; struct drm_device *drm_dev; @@ -196,6 +199,35 @@ static int dp_test_active_open(struct inode *inode, inode->i_private); } +static ssize_t dp_hdcp_key_write(struct file *file, const char __user *ubuf, +size_t len, loff_t *offp) +{ + char *input_buffer; + int ret; + struct dp_debug_private *debug = file->private_data; + + if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN)) + return -EINVAL; + + if (!debug->hdcp) + return -ENOENT; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_ERR(input_buffer); + + ret = dp_hdcp_ingest_key(debug->hdcp, input_buffer, len); + + kfree(input_buffer); + if (ret < 0) { + DRM_ERROR("Could not ingest HDCP key, ret=%d\n", ret); + return ret; + } + + *offp += len; + return len; +} + static const struct file_operations test_active_fops = { .owner = THIS_MODULE, .open = dp_test_active_open, @@ -205,6 +237,12 @@ static const struct file_operations test_active_fops = { .write = dp_test_activ
[Intel-gfx] [PATCH v7 09/10] arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
From: Sean Paul Add the register ranges required for HDCP key injection and HDCP TrustZone interaction as described in the dt-bindings for the sc7180 dp controller. Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v3: -Split off into a new patch containing just the dts change (Stephen) -Add hdcp compatible string (Stephen) Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Put the tz register offsets in trogdor dtsi (Rob C) Changes in v6: -Rebased: Removed modifications in sc7180.dtsi as it's already upstream Changes in v7: -Change registers offset arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index 47f39c547c41a..63183ac9c3c48 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -816,6 +816,14 @@ &mdss_dp { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&dp_hot_plug_det>; + + reg = <0 0x0ae9 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>, + <0 0x0aed1000 0 0x174>, + <0 0x0aee1000 0 0x2c>; }; &mdss_dp_out { -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 08/10] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul Add the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. Cc: Rob Herring Cc: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Drop register range names (Stephen) -Fix yaml errors (Rob) Changes in v3: -Add new compatible string for dp-hdcp -Add descriptions to reg -Add minItems/maxItems to reg -Make reg depend on the new hdcp compatible string Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v4.5: -Remove maxItems from reg (Rob) -Remove leading zeros in example (Rob) Changes in v5: -None Changes in v6: -Rebased: modify minItems instead of adding it as new line. Changes in v7: -Revert the change to minItems -Added the maxItems to Reg .../devicetree/bindings/display/msm/dp-controller.yaml | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 774ccb5184b88..c47ade3a4ae17 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -31,6 +31,8 @@ properties: - description: link register block - description: p0 register block - description: p1 register block + - description: (Optional) Registers for HDCP device key injection + - description: (Optional) Registers for HDCP TrustZone interaction interrupts: maxItems: 1 @@ -158,6 +160,7 @@ allOf: aux-bus: false reg: minItems: 5 + maxItems: 7 required: - "#sound-dai-cells" @@ -175,7 +178,9 @@ examples: <0xae90200 0x200>, <0xae90400 0xc00>, <0xae91000 0x400>, - <0xae91400 0x400>; + <0xae91400 0x400>, + <0xaed1000 0x174>, + <0xaee1000 0x2c>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: - None drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000aa..0a20bc41be55d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 04/10] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul Expand upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the shim vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Acked-by: Jani Nikula Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Fixed typo in function descriptions -Rebased: Moved the new code between drm_hdcp.h and drm_hdcp_helper.c/h -Add missing headers. Reported-by: kernel test robot Changes in v7: - Add a |driver_data| field to some functions in drm_hdcp_helper_funcs that are called by the driver so drivers can pass anything they such as bridges - Isolate all non-common code between HDMI and DP into separate functions instead of manually checking for datra->aux drivers/gpu/drm/display/drm_hdcp_helper.c | 1211 + include/drm/display/drm_hdcp.h| 287 + include/drm/display/drm_hdcp_helper.h | 51 +- 3 files changed, 1548 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 3ee1a6ae26c53..40ea10869736c 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -6,13 +6,18 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -507,3 +512,1209 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP_V_PRIME(4) }, + .bcaps = DP_AUX_HDCP_BCAPS, + .bcaps_mask_repeater_present = DP_BCAPS_REPEATER_PRESENT, + + /* +* For some reason the HDMI and DP HDCP specs call this register +* definition by different names. In the HDMI spec, it's called BSTATUS, +* but in DP it's called BINFO. +*/ + .bstatus = DP_AUX_HDCP_BINFO, +}; + +/* + * Read a DPCD register. + * + * @data: drm_hdcp_helper_data containing the DisplayPort AUX channel (SST or MST) + * @offset: address of the (first) register to read + * @value: buffer to store the register values + * @len: number of bytes in @value + * + * Return: 0 on success or a negativ
[Intel-gfx] [PATCH v7 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased Changes in v7: -None .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7bcd90384a46d..a14b86a07e545 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -494,6 +494,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -501,8 +502,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55d..61a862ae1f286 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2373,21 +2373,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if (intel_hdcp2_capable(c
[Intel-gfx] [PATCH v7 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, rename to drm_hdcp_has_changed and return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Renamed the function from drm_hdcp_atomic_check to drm_hdcp_has_changed (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 39 ++--- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7ca390b3ea106..34baf2b97cd87 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -422,18 +422,21 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, EXPORT_SYMBOL(drm_hdcp_update_content_protection); /** - * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * drm_hdcp_has_changed - Helper for drivers to call during connector->atomic_check * * @state: pointer to the atomic state being checked * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) +bool drm_hdcp_has_changed(struct drm_connector *connector, + struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; struct drm_crtc_state *new_crtc_state; @@ -450,19 +453,31 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from UNDESIRED state, CRTC change or re-enablement requires +* the driver to try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -477,9 +492,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } -EXPORT_SYMBOL(drm_hdcp_atomic_check); +EXPORT_SYMBOL(drm_hdcp_has_changed); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 934ca9dcecc54..bce4aba752974 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -123,8 +123,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdc
[Intel-gfx] [PATCH v7 03/10] drm/hdcp: Update property value on content type and user changes
From: Sean Paul Update the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Rebased as function name has changed. drivers/gpu/drm/display/drm_hdcp_helper.c | 29 +++ 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 34baf2b97cd87..3ee1a6ae26c53 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -480,21 +480,30 @@ bool drm_hdcp_has_changed(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change -* - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* Content type changes require an HDCP disable/enable cycle. */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if (new_conn_state->hdcp_content_type != + old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: +* - HDCP was activated since the last commit +* - Attempting to set to desired while already enabled +*/ + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_has_changed); -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul Move the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Dmitry Baryshkov Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c Changes in v7: -Removed links to patch from commit msg (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 64 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 --- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd77..7ca390b3ea106 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,66 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 6621aa245caf4..934ca9dcecc54 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -39,7 +40,6 @@ #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "skl_universal_plane.h" @@ -123,7 +123,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn
[Intel-gfx] [PATCH v7 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers
From: Mark Yacoub Hi all, This is v7 of the HDCP patches. The patches are authored by Sean Paul. I rebased and addressed the review comments in v6-v7. Patches 1-4 focus on moving the common HDCP helpers to common DRM. This introduces a slight change in the original intel flow as it splits the unique driver protocol from the generic implementation. Patches 5-7 split the HDCP flow on i915 driver to make use the common DRM helpers. Patches 8-10 implement HDCP on MSM driver. (Note: I resent the patch to add missing cc's) Thanks, -Mark Yacoub Sean Paul (10): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 dt-bindings: msm/dp: Add bindings for HDCP registers arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |7 +- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi |8 + drivers/gpu/drm/display/drm_hdcp_helper.c | 1299 + drivers/gpu/drm/i915/display/intel_atomic.c |8 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 11 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 368 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1036 +++-- drivers/gpu/drm/i915/display/intel_hdcp.h | 42 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 276 ++-- drivers/gpu/drm/msm/Kconfig |1 + drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/dp/dp_debug.c | 48 +- drivers/gpu/drm/msm/dp/dp_debug.h | 17 +- drivers/gpu/drm/msm/dp/dp_display.c | 42 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 39 +- drivers/gpu/drm/msm/dp/dp_drm.h | 12 +- drivers/gpu/drm/msm/dp/dp_hdcp.c | 483 ++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 31 + drivers/gpu/drm/msm/dp/dp_parser.c| 19 + drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 30 +- drivers/gpu/drm/msm/msm_atomic.c | 19 + include/drm/display/drm_hdcp.h| 287 include/drm/display/drm_hdcp_helper.h | 52 + 28 files changed, 2903 insertions(+), 1341 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- 2.40.0.348.gf938b09366-goog
Re: [Intel-gfx] [PATCH v6 07/10] drm/i915/hdcp: Use HDCP helpers for i915
On Tue, Mar 14, 2023 at 1:54 AM Kandpal, Suraj wrote: > > > > > From: Sean Paul > > > > 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. > > > > Acked-by: Jani Nikula > > Signed-off-by: Sean Paul > > Signed-off-by: Mark Yacoub > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-8- > > s...@poorly.run #v1 > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-8- > > s...@poorly.run #v2 > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-8- > > s...@poorly.run #v3 > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845- > > 8-s...@poorly.run #v4 > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308- > > 8-s...@poorly.run #v5 > > > > Changes in v2: > > -Fix mst helper function pointer reported by 0-day > > Changes in v3: > > -Add forward declaration for drm_atomic_state in intel_hdcp.h identified > > by 0-day > > Changes in v4: > > -None > > Changes in v5: > > -None > > Changes in v6: > > -Rebased. > > > > --- > > drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- > > .../drm/i915/display/intel_display_debugfs.c | 6 +- > > .../drm/i915/display/intel_display_types.h| 60 +- > > drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 348 +++ > > drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- > > drivers/gpu/drm/i915/display/intel_hdcp.c | 952 +++--- > > drivers/gpu/drm/i915/display/intel_hdcp.h | 31 +- > > drivers/gpu/drm/i915/display/intel_hdmi.c | 270 ++--- > > 8 files changed, 445 insertions(+), 1270 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c > > b/drivers/gpu/drm/i915/display/intel_ddi.c > > index 69ecf2a3d6c6..a4397f066a3e 100644 > > --- a/drivers/gpu/drm/i915/display/intel_ddi.c > > +++ b/drivers/gpu/drm/i915/display/intel_ddi.c > > @@ -28,6 +28,7 @@ > > #include > > > > #include > > +#include > > #include > > > > #include "i915_drv.h" > > @@ -2909,6 +2910,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) > > @@ -2925,12 +2930,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, > > @@ -2976,7 +2979,14 @@ static void intel_disable_ddi(struct > > intel_atomic_state *state, > &
Re: [Intel-gfx] [PATCH v6 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
On Thu, Mar 23, 2023 at 3:18 AM Kandpal, Suraj wrote: > > > > > -Original Message- > > From: Kandpal, Suraj > > Sent: Friday, March 10, 2023 1:55 PM > > To: Mark Yacoub ; quic_khs...@quicinc.com; > > linux-arm-...@vger.kernel.org; dri-de...@lists.freedesktop.org; > > freedr...@lists.freedesktop.org; devicet...@vger.kernel.org; linux- > > ker...@vger.kernel.org; intel-gfx@lists.freedesktop.org > > Cc: quic_sbill...@quicinc.com; konrad.dyb...@somainline.org; Souza, Jose > > ; bjorn.anders...@linaro.org; > > krzysztof.kozlowski...@linaro.org; hbh...@gmail.com; Vasut, Marek > > ; Dixit, Ashutosh ; > > s...@poorly.run; abhin...@codeaurora.org; javi...@redhat.com; Murthy, > > Arun R ; Lisovskiy, Stanislav > > ; agr...@kernel.org; > > quic_jessz...@quicinc.com; Nautiyal, Ankit K ; > > Nikula, Jani ; De Marchi, Lucas > > ; quic_abhin...@quicinc.com; > > swb...@chromium.org; robh...@kernel.org; > > christophe.jail...@wanadoo.fr; max...@cerno.tech; Vivi, Rodrigo > > ; johan+lin...@kernel.org; > > tvrtko.ursu...@linux.intel.com; anders...@kernel.org; > > diand...@chromium.org; Sharma, Swati2 ; > > Navare, Manasi D ; tzimmerm...@suse.de; > > Modem, Bhanuprakash ; > > dmitry.barysh...@linaro.org; seanp...@chromium.org > > Subject: RE: [PATCH v6 06/10] drm/i915/hdcp: Retain hdcp_capable return > > codes > > > > > Subject: [PATCH v6 06/10] drm/i915/hdcp: Retain hdcp_capable return > > > codes > > > > > > From: Sean Paul > > > > > > The shim functions return error codes, but they are discarded in > > > intel_hdcp.c. This patch plumbs the return codes through so they are > > > properly handled. > > > > > > Acked-by: Jani Nikula > > > Reviewed-by: Rodrigo Vivi > > > Signed-off-by: Sean Paul > > > Signed-off-by: Mark Yacoub > > > Link: > > > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-7- > > > s...@poorly.run #v1 > > > Link: > > > https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-7- > > > s...@poorly.run #v2 > > > Link: > > > https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-7- > > > s...@poorly.run #v3 > > > Link: > > > > > https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845- > > > 7-s...@poorly.run #v4 > > > Link: > > > > > https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308- > > > 7-s...@poorly.run #v5 > > > > > > Changes in v2: > > > -None > > > Changes in v3: > > > -None > > > Changes in v4: > > > -None > > > Changes in v5: > > > -None > > > Changes in v6: > > > -Rebased > > > > > > --- > > > .../drm/i915/display/intel_display_debugfs.c | 9 +++- > > > drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- > > > drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- > > > 3 files changed, 37 insertions(+), 27 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c > > > b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > > > index 7c7253a2541c..13a4153bb76e 100644 > > > --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c > > > +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c > > > @@ -492,6 +492,7 @@ static void intel_panel_info(struct seq_file *m, > > > static void intel_hdcp_info(struct seq_file *m, > > > struct intel_connector *intel_connector) { > > > + int ret; > > > bool hdcp_cap, hdcp2_cap; > > > > > > if (!intel_connector->hdcp.shim) { > > > @@ -499,8 +500,12 @@ static void intel_hdcp_info(struct seq_file *m, > > > goto out; > > > } > > > > > > - hdcp_cap = intel_hdcp_capable(intel_connector); > > > - hdcp2_cap = intel_hdcp2_capable(intel_connector); > > > + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); > > > + if (ret) > > > + hdcp_cap = false; > > > + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); > > > + if (ret) > > > + hdcp2_cap = false; > > > > > > > This does not seem to be adding value here as this error which you referred > > to as being ignored is used both in case of hdmi and dp is being to > > determine > > if hdcp_cap or hdcp2 cap is true or false which you basically
[Intel-gfx] [PATCH v7 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Acked-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. Changes in v7: -Added to drm_hdcp_helper_funcs new functions that are unique between DP and HDMI -Adjusted the function signatures to take "driver data" drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 6 +- .../drm/i915/display/intel_display_types.h| 51 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 368 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 960 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 37 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 276 ++--- 8 files changed, 484 insertions(+), 1262 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 0f1ec2a98cc87..550a99d1811b4 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2941,6 +2942,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2957,12 +2962,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, @@ -3008,7 +3011,14 @@ 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, @@ -3036,13 +3046,19 @@ 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-gfx] [PATCH v7 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None Changes in v7: - None drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000aa..0a20bc41be55d 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.40.0.348.gf938b09366-goog
[Intel-gfx] [PATCH v7 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased Changes in v7: -None .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7bcd90384a46d..a14b86a07e545 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -494,6 +494,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -501,8 +502,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55d..61a862ae1f286 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; + bool capable; int ret = -EINVAL; if (!hdcp->shim) @@ -2373,21 +2373,27 @@ int intel_hdcp_enable(struct intel_connector *connector, * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup * is capable of HDCP2.2, it is preferred to use HDCP2.2. */ - if (intel_hdcp2_capable(c
[Intel-gfx] [PATCH v7 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, rename to drm_hdcp_has_changed and return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c Changes in v7: -Renamed the function from drm_hdcp_atomic_check to drm_hdcp_has_changed (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 39 ++--- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7ca390b3ea106..34baf2b97cd87 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -422,18 +422,21 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, EXPORT_SYMBOL(drm_hdcp_update_content_protection); /** - * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * drm_hdcp_has_changed - Helper for drivers to call during connector->atomic_check * * @state: pointer to the atomic state being checked * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, - struct drm_atomic_state *state) +bool drm_hdcp_has_changed(struct drm_connector *connector, + struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; struct drm_crtc_state *new_crtc_state; @@ -450,19 +453,31 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from UNDESIRED state, CRTC change or re-enablement requires +* the driver to try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -477,9 +492,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } -EXPORT_SYMBOL(drm_hdcp_atomic_check); +EXPORT_SYMBOL(drm_hdcp_has_changed); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 934ca9dcecc54..bce4aba752974 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -123,8 +123,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdc
[Intel-gfx] [PATCH v7 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul Move the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Dmitry Baryshkov Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub --- Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c Changes in v7: -Removed links to patch from commit msg (Dmitry Baryshkov) drivers/gpu/drm/display/drm_hdcp_helper.c | 64 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 --- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd77..7ca390b3ea106 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,66 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 6621aa245caf4..934ca9dcecc54 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -39,7 +40,6 @@ #include "intel_cdclk.h" #include "intel_display_types.h" #include "intel_global_state.h" -#include "intel_hdcp.h" #include "intel_psr.h" #include "skl_universal_plane.h" @@ -123,7 +123,7 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn
[Intel-gfx] [PATCH v6 10/10] drm/msm: Implement HDCP 1.x using the new drm HDCP helpers
From: Sean Paul This patch adds HDCP 1.x support to msm DP connectors using the new HDCP helpers. Cc: Stephen Boyd Cc: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-14-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-15-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-15-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-11-s...@poorly.run #v5 Changes in v2: -Squash [1] into this patch with the following changes (Stephen) -Update the sc7180 dtsi file -Remove resource names and just use index (Stephen) Changes in v3: -Split out the dtsi change from v2 (Stephen) -Fix set-but-unused warning identified by 0-day -Fix up a couple of style nits (Stephen) -Store HDCP key directly in dp_hdcp struct (Stephen) -Remove wmb in HDCP key initialization, move an_seed (Stephen) -Use FIELD_PREP for bstatus/bcaps (Stephen) -#define read_poll_timeout values (Stephen) -Remove unnecessary parentheses in dp_hdcp_store_ksv_fifo (Stephen) -Add compatible string for hdcp (Stephen) -Rename dp_hdcp_write_* functions (Abhinav) -Add 1us delay between An reads (Abhinav) -Delete unused dp_hdcp_read_* functions Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Change return check of drm_hdcp_helper_initialize_dp() (Stephen) Changes in v6: -Change the tracking of the state from connector state to bridge as state as drm_connector_state is no longer tracked and the functionality has moved to msm_dp_bridge [1] https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-14-s...@poorly.run --- drivers/gpu/drm/msm/Kconfig | 1 + drivers/gpu/drm/msm/Makefile| 1 + drivers/gpu/drm/msm/dp/dp_debug.c | 48 ++- drivers/gpu/drm/msm/dp/dp_debug.h | 6 +- drivers/gpu/drm/msm/dp/dp_display.c | 52 +++- drivers/gpu/drm/msm/dp/dp_display.h | 5 + drivers/gpu/drm/msm/dp/dp_drm.c | 108 ++- drivers/gpu/drm/msm/dp/dp_drm.h | 16 +- drivers/gpu/drm/msm/dp/dp_hdcp.c| 456 drivers/gpu/drm/msm/dp/dp_hdcp.h| 29 ++ drivers/gpu/drm/msm/dp/dp_parser.c | 20 +- drivers/gpu/drm/msm/dp/dp_parser.h | 4 + drivers/gpu/drm/msm/dp/dp_reg.h | 32 +- drivers/gpu/drm/msm/msm_atomic.c| 15 + 14 files changed, 772 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 61ca0c0757bc..9d9a66d9156c 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -15,6 +15,7 @@ config DRM_MSM select REGULATOR select DRM_DP_AUX_BUS select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER select DRM_DISPLAY_HELPER select DRM_KMS_HELPER select DRM_PANEL diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7274c41228ed..a73e7b858af2 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -122,6 +122,7 @@ msm-$(CONFIG_DRM_MSM_DP)+= dp/dp_aux.o \ dp/dp_ctrl.o \ dp/dp_display.o \ dp/dp_drm.o \ + dp/dp_hdcp.o \ dp/dp_hpd.o \ dp/dp_link.o \ dp/dp_panel.o \ diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 5e35033ba3e4..e97d27edbb13 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "dp_parser.h" #include "dp_catalog.h" @@ -15,6 +16,7 @@ #include "dp_ctrl.h" #include "dp_debug.h" #include "dp_display.h" +#include "dp_hdcp.h" #define DEBUG_NAME "msm_dp" @@ -25,6 +27,7 @@ struct dp_debug_private { struct dp_link *link; struct dp_panel *panel; struct drm_connector *connector; + struct dp_hdcp *hdcp; struct device *dev; struct drm_device *drm_dev; @@ -196,6 +199,35 @@ static int dp_test_active_open(struct inode *inode, inode->i_private); } +static ssize_t dp_hdcp_key_write(struct file *file, const char __user *ubuf, +size_t len, loff_t *offp) +{ + char *input_buffer; + int ret; + struct dp_debug_private *debug = file->private_data; + + if (len != (DRM_HDCP_KSV_LEN + DP_HDCP_NUM_KEYS * DP_HDCP_KEY_LEN)) + return -EINVAL; + + if (!debug->hdcp) + return -ENOENT; + + input_buffer = memdup_user_nul(ubuf, len); + if (IS_ERR(input_buffer)) + return PTR_
[Intel-gfx] [PATCH v6 09/10] arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller
From: Sean Paul This patch adds the register ranges required for HDCP key injection and HDCP TrustZone interaction as described in the dt-bindings for the sc7180 dp controller. Now that these are supported, change the compatible string to "dp-hdcp". Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-15-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-14-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-14-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-14-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-10-s...@poorly.run #v5 Changes in v3: -Split off into a new patch containing just the dts change (Stephen) -Add hdcp compatible string (Stephen) Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v5: -Put the tz register offsets in trogdor dtsi (Rob C) Changes in v6: -Rebased: Removed modifications in sc7180.dtsi as it's already upstream --- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index 178efaaa89ec..6f6fe5cb6563 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -817,6 +817,14 @@ &mdss_dp { pinctrl-names = "default"; pinctrl-0 = <&dp_hot_plug_det>; data-lanes = <0 1>; + + reg = <0 0x0ae9 0 0x200>, + <0 0x0ae90200 0 0x200>, + <0 0x0ae90400 0 0xc00>, + <0 0x0ae91000 0 0x400>, + <0 0x0ae91400 0 0x400>, + <0 0x0aed1000 0 0x175>, + <0 0x0aee1000 0 0x2c>; }; &pm6150_adc { -- 2.39.0.246.g2a6d74b583-goog
[Intel-gfx] [PATCH v6 08/10] dt-bindings: msm/dp: Add bindings for HDCP registers
From: Sean Paul This patch adds the bindings for the MSM DisplayPort HDCP registers which are required to write the HDCP key into the display controller as well as the registers to enable HDCP authentication/key exchange/encryption. We'll use a new compatible string for this since the fields are optional. Cc: Rob Herring Cc: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-13-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-13-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-13-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-13-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/2025202153.117244-1-s...@poorly.run #v4.5 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-9-s...@poorly.run #v5 Changes in v2: -Drop register range names (Stephen) -Fix yaml errors (Rob) Changes in v3: -Add new compatible string for dp-hdcp -Add descriptions to reg -Add minItems/maxItems to reg -Make reg depend on the new hdcp compatible string Changes in v4: -Rebase on Bjorn's multi-dp patchset Changes in v4.5: -Remove maxItems from reg (Rob) -Remove leading zeros in example (Rob) Changes in v5: -None Changes in v6: -Rebased: modify minItems instead of adding it as new line. --- .../devicetree/bindings/display/msm/dp-controller.yaml| 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index f2515af8256f..17d741f9af86 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -24,13 +24,15 @@ properties: - qcom,sm8350-dp reg: -minItems: 4 +minItems: 5 items: - description: ahb register block - description: aux register block - description: link register block - description: p0 register block - description: p1 register block + - description: (Optional) Registers for HDCP device key injection + - description: (Optional) Registers for HDCP TrustZone interaction interrupts: maxItems: 1 @@ -154,7 +156,9 @@ examples: <0xae90200 0x200>, <0xae90400 0xc00>, <0xae91000 0x400>, - <0xae91400 0x400>; + <0xae91400 0x400>, + <0xaed1000 0x174>, + <0xaee1000 0x2c>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.39.0.246.g2a6d74b583-goog
[Intel-gfx] [PATCH v6 07/10] drm/i915/hdcp: Use HDCP helpers for i915
From: Sean Paul 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. Acked-by: Jani Nikula Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-8-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-8-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-8-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-8-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-8-s...@poorly.run #v5 Changes in v2: -Fix mst helper function pointer reported by 0-day Changes in v3: -Add forward declaration for drm_atomic_state in intel_hdcp.h identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased. --- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 6 +- .../drm/i915/display/intel_display_types.h| 60 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 348 +++ drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 952 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 31 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 270 ++--- 8 files changed, 445 insertions(+), 1270 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 69ecf2a3d6c6..a4397f066a3e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -28,6 +28,7 @@ #include #include +#include #include #include "i915_drv.h" @@ -2909,6 +2910,10 @@ 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 (!intel_crtc_is_bigjoiner_slave(crtc_state)) @@ -2925,12 +2930,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, @@ -2976,7 +2979,14 @@ 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, @@ -3004,13 +3014,19 @@ void intel_ddi_update_pipe(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + str
[Intel-gfx] [PATCH v6 05/10] drm/i915/hdcp: Consolidate HDCP setup/state cache
From: Sean Paul Stick all of the setup for HDCP into a dedicated function. No functional change, but this will facilitate moving HDCP logic into helpers. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-6-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-6-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-6-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-6-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-6-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -None --- drivers/gpu/drm/i915/display/intel_hdcp.c | 52 +++ 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 396d2cef000a..0a20bc41be55 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2190,6 +2190,37 @@ static enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder) } } +static int +_intel_hdcp_setup(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, u8 content_type) +{ + struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_hdcp *hdcp = &connector->hdcp; + int ret = 0; + + if (!connector->encoder) { + drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", + connector->base.name, connector->base.base.id); + return -ENODEV; + } + + hdcp->content_type = content_type; + + if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { + hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; + hdcp->stream_transcoder = pipe_config->cpu_transcoder; + } else { + hdcp->cpu_transcoder = pipe_config->cpu_transcoder; + hdcp->stream_transcoder = INVALID_TRANSCODER; + } + + if (DISPLAY_VER(dev_priv) >= 12) + dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + + return ret; +} + static int initialize_hdcp_port_data(struct intel_connector *connector, struct intel_digital_port *dig_port, const struct intel_hdcp_shim *shim) @@ -2329,28 +2360,14 @@ int intel_hdcp_enable(struct intel_connector *connector, if (!hdcp->shim) return -ENOENT; - if (!connector->encoder) { - drm_err(&dev_priv->drm, "[%s:%d] encoder is not initialized\n", - connector->base.name, connector->base.base.id); - return -ENODEV; - } - mutex_lock(&hdcp->mutex); mutex_lock(&dig_port->hdcp_mutex); drm_WARN_ON(&dev_priv->drm, hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); - hdcp->content_type = content_type; - - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_DP_MST)) { - hdcp->cpu_transcoder = pipe_config->mst_master_transcoder; - hdcp->stream_transcoder = pipe_config->cpu_transcoder; - } else { - hdcp->cpu_transcoder = pipe_config->cpu_transcoder; - hdcp->stream_transcoder = INVALID_TRANSCODER; - } - if (DISPLAY_VER(dev_priv) >= 12) - dig_port->hdcp_port_data.fw_tc = intel_get_mei_fw_tc(hdcp->cpu_transcoder); + ret = _intel_hdcp_setup(connector, pipe_config, content_type); + if (ret) + goto out; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -2378,6 +2395,7 @@ int intel_hdcp_enable(struct intel_connector *connector, true); } +out: mutex_unlock(&dig_port->hdcp_mutex); mutex_unlock(&hdcp->mutex); return ret; -- 2.39.0.246.g2a6d74b583-goog
[Intel-gfx] [PATCH v6 06/10] drm/i915/hdcp: Retain hdcp_capable return codes
From: Sean Paul The shim functions return error codes, but they are discarded in intel_hdcp.c. This patch plumbs the return codes through so they are properly handled. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-7-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-7-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-7-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-7-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-7-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased --- .../drm/i915/display/intel_display_debugfs.c | 9 +++- drivers/gpu/drm/i915/display/intel_hdcp.c | 51 ++- drivers/gpu/drm/i915/display/intel_hdcp.h | 4 +- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 7c7253a2541c..13a4153bb76e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -492,6 +492,7 @@ static void intel_panel_info(struct seq_file *m, static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector) { + int ret; bool hdcp_cap, hdcp2_cap; if (!intel_connector->hdcp.shim) { @@ -499,8 +500,12 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_capable(intel_connector); - hdcp2_cap = intel_hdcp2_capable(intel_connector); + ret = intel_hdcp_capable(intel_connector, &hdcp_cap); + if (ret) + hdcp_cap = false; + ret = intel_hdcp2_capable(intel_connector, &hdcp2_cap); + if (ret) + hdcp2_cap = false; if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 0a20bc41be55..61a862ae1f28 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -177,50 +177,49 @@ int intel_hdcp_read_valid_bksv(struct intel_digital_port *dig_port, } /* Is HDCP1.4 capable on Platform and Sink */ -bool intel_hdcp_capable(struct intel_connector *connector) +int intel_hdcp_capable(struct intel_connector *connector, bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); const struct intel_hdcp_shim *shim = connector->hdcp.shim; - bool capable = false; u8 bksv[5]; + *capable = false; + if (!shim) - return capable; + return 0; - if (shim->hdcp_capable) { - shim->hdcp_capable(dig_port, &capable); - } else { - if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) - capable = true; - } + if (shim->hdcp_capable) + return shim->hdcp_capable(dig_port, capable); + + if (!intel_hdcp_read_valid_bksv(dig_port, shim, bksv)) + *capable = true; - return capable; + return 0; } /* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +int intel_hdcp2_capable(struct intel_connector *connector, bool *capable) { 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; - bool capable = false; + + *capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) - return false; + return 0; /* MEI interface is solid */ 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); - return false; + return 0; } mutex_unlock(&dev_priv->display.hdcp.comp_mutex); /* Sink's capability for HDCP2.2 */ - hdcp->shim->hdcp_2_2_capable(dig_port, &capable); - - return capable; + return hdcp->shim->hdcp_2_2_capable(dig_port, capable); } static bool intel_hdcp_in_use(struct drm_i915_private *dev_priv, @@ -2355,6 +2354,7 @@ int intel_hdcp_enable(struct intel_connector *connector, struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct inte
[Intel-gfx] [PATCH v6 04/10] drm/hdcp: Expand HDCP helper library for enable/disable/check
From: Sean Paul This patch expands upon the HDCP helper library to manage HDCP enable, disable, and check. Previous to this patch, the majority of the state management and sink interaction is tucked inside the Intel driver with the understanding that once a new platform supported HDCP we could make good decisions about what should be centralized. With the addition of HDCP support for Qualcomm, it's time to migrate the protocol-specific bits of HDCP authentication, key exchange, and link checks to the HDCP helper. In terms of functionality, this migration is 1:1 with the Intel driver, however things are laid out a bit differently than with intel_hdcp.c, which is why this is a separate patch from the i915 transition to the helper. On i915, the shim vtable is used to account for HDMI vs. DP vs. DP-MST differences whereas the helper library uses a LUT to account for the register offsets and a remote read function to route the messages. On i915, storing the sink information in the source is done inline whereas now we use the new drm_hdcp_helper_funcs vtable to store and fetch information to/from source hw. Finally, instead of calling enable/disable directly from the driver, we'll leave that decision to the helper and by calling drm_hdcp_helper_atomic_commit() from the driver. All told, this will centralize the protocol and state handling in the helper, ensuring we collect all of our bugs^Wlogic in one place. Cc: Abhinav Kumar Acked-by: Jani Nikula Reviewed-by: Abhinav Kumar Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-5-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-5-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-5-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-5-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-5-s...@poorly.run #v5 Changes in v2: -Fixed set-but-unused variable identified by 0-day Changes in v3: -Fixed uninitialized variable warning identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Fixed typo in function descriptions -Rebased: Moved the new code between drm_hdcp.h and drm_hdcp_helper.c/h -Add missing headers. Reported-by: kernel test robot --- drivers/gpu/drm/display/drm_hdcp_helper.c | 1109 + include/drm/display/drm_hdcp.h| 168 +++- include/drm/display/drm_hdcp_helper.h | 30 +- 3 files changed, 1305 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index ce92f1cac251..de8c006b9cda 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -6,13 +6,18 @@ * Ramalingam C */ +#include #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -512,3 +517,1107 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); + +struct drm_hdcp_helper_data { + struct mutex mutex; + struct mutex *driver_mutex; + + struct drm_connector *connector; + const struct drm_hdcp_helper_funcs *funcs; + + u64 value; + unsigned int enabled_type; + + struct delayed_work check_work; + struct work_struct prop_work; + + struct drm_dp_aux *aux; + const struct drm_hdcp_hdcp1_receiver_reg_lut *hdcp1_lut; +}; + +struct drm_hdcp_hdcp1_receiver_reg_lut { + unsigned int bksv; + unsigned int ri; + unsigned int aksv; + unsigned int an; + unsigned int ainfo; + unsigned int v[5]; + unsigned int bcaps; + unsigned int bcaps_mask_repeater_present; + unsigned int bstatus; +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_ddc_lut = { + .bksv = DRM_HDCP_DDC_BKSV, + .ri = DRM_HDCP_DDC_RI_PRIME, + .aksv = DRM_HDCP_DDC_AKSV, + .an = DRM_HDCP_DDC_AN, + .ainfo = DRM_HDCP_DDC_AINFO, + .v = { DRM_HDCP_DDC_V_PRIME(0), DRM_HDCP_DDC_V_PRIME(1), + DRM_HDCP_DDC_V_PRIME(2), DRM_HDCP_DDC_V_PRIME(3), + DRM_HDCP_DDC_V_PRIME(4) }, + .bcaps = DRM_HDCP_DDC_BCAPS, + .bcaps_mask_repeater_present = DRM_HDCP_DDC_BCAPS_REPEATER_PRESENT, + .bstatus = DRM_HDCP_DDC_BSTATUS, +}; + +static const struct drm_hdcp_hdcp1_receiver_reg_lut drm_hdcp_hdcp1_dpcd_lut = { + .bksv = DP_AUX_HDCP_BKSV, + .ri = DP_AUX_HDCP_RI_PRIME, + .aksv = DP_AUX_HDCP_AKSV, + .an = DP_AUX_HDCP_AN, + .ainfo = DP_AUX_HDCP_AINFO, + .v = { DP_AUX_HDCP_V_PRIME(0), DP_AUX_HDCP_V_PRIME(1), + DP_AUX_HDCP_V_PRIME(2), DP_AUX_HDCP_V_PRIME(3), + DP_AUX_HDCP
[Intel-gfx] [PATCH v6 03/10] drm/hdcp: Update property value on content type and user changes
From: Sean Paul This patch updates the connector's property value in 2 cases which were previously missed: 1- Content type changes. The value should revert back to DESIRED from ENABLED in case the driver must re-authenticate the link due to the new content type. 2- Userspace sets value to DESIRED while ENABLED. In this case, the value should be reset immediately to ENABLED since the link is actively being encrypted. To accommodate these changes, I've split up the conditionals to make things a bit more clear (as much as one can with this mess of state). Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Abhinav Kumar Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-4-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-4-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-4-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-4-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-4-s...@poorly.run Changes in v2: -None Changes in v3: -Fixed indentation issue identified by 0-day Changes in v4: -None Changes in v5: -None Changes in v6: -Rebased: modifications in drm_hdcp_helper.c instead of drm_hdcp.c --- drivers/gpu/drm/display/drm_hdcp_helper.c | 29 +++ 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index a3896b0904b5..ce92f1cac251 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -485,21 +485,30 @@ bool drm_hdcp_atomic_check(struct drm_connector *connector, return true; /* -* Nothing to do if content type is unchanged and one of: -* - state didn't change -* - HDCP was activated since the last commit -* - attempting to set to desired while already enabled +* Content type changes require an HDCP disable/enable cycle. */ - if (old_hdcp == new_hdcp || - (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + if (new_conn_state->hdcp_content_type != + old_conn_state->hdcp_content_type) { + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Ignore meaningless state changes: +* - HDCP was activated since the last commit +* - Attempting to set to desired while already enabled +*/ + if ((old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { - if (old_conn_state->hdcp_content_type == - new_conn_state->hdcp_content_type) - return false; + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_ENABLED; + return false; } - return true; + /* Finally, if state changes, we need action */ + return old_hdcp != new_hdcp; } EXPORT_SYMBOL(drm_hdcp_atomic_check); -- 2.39.0.246.g2a6d74b583-goog
[Intel-gfx] [PATCH v6 02/10] drm/hdcp: Avoid changing crtc state in hdcp atomic check
From: Sean Paul Instead of forcing a modeset in the hdcp atomic check, simply return true if the content protection value is changing and let the driver decide whether a modeset is required or not. Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-3-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-3-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-3-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-3-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-3-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in V6: -Rebase: modifications in drm_hdcp_helper.c instead of drm_hdcp.c --- drivers/gpu/drm/display/drm_hdcp_helper.c | 33 +++-- drivers/gpu/drm/i915/display/intel_atomic.c | 6 ++-- include/drm/display/drm_hdcp_helper.h | 2 +- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index 7d910523b05f..a3896b0904b5 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -428,11 +428,14 @@ EXPORT_SYMBOL(drm_hdcp_update_content_protection); * @connector: drm_connector on which content protection state needs an update * * This function can be used by display drivers to perform an atomic check on the - * hdcp state elements. If hdcp state has changed, this function will set - * mode_changed on the crtc driving the connector so it can update its hardware - * to match the hdcp state. + * hdcp state elements. If hdcp state has changed in a manner which requires the + * driver to enable or disable content protection, this function will return + * true. + * + * Returns: + * true if the driver must enable/disable hdcp, false otherwise */ -void drm_hdcp_atomic_check(struct drm_connector *connector, +bool drm_hdcp_atomic_check(struct drm_connector *connector, struct drm_atomic_state *state) { struct drm_connector_state *new_conn_state, *old_conn_state; @@ -450,10 +453,12 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, * If the connector is being disabled with CP enabled, mark it * desired so it's re-enabled when the connector is brought back */ - if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; - return; + return true; + } + return false; } new_crtc_state = @@ -465,9 +470,19 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, */ if (drm_atomic_crtc_needs_modeset(new_crtc_state) && (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && -new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) { new_conn_state->content_protection = DRM_MODE_CONTENT_PROTECTION_DESIRED; + return true; + } + + /* +* Coming back from disable or changing CRTC with DESIRED state requires +* that the driver try CP enable. +*/ + if (new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && + new_conn_state->crtc != old_conn_state->crtc) + return true; /* * Nothing to do if content type is unchanged and one of: @@ -482,9 +497,9 @@ void drm_hdcp_atomic_check(struct drm_connector *connector, new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { if (old_conn_state->hdcp_content_type == new_conn_state->hdcp_content_type) - return; + return false; } - new_crtc_state->mode_changed = true; + return true; } EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index 8a473199c4bf..a2067cbae2d5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -123,8 +123,6 @@ int intel_digital_connector_atomic_check(struct drm_connector *conn, to_intel_digital_connector_state(old_state); struct drm_crtc_state *crtc_state; - drm_hdcp_atomic_check(conn, state); - if (!new_state->crtc) return 0; @@ -140,8 +138
[Intel-gfx] [PATCH v6 01/10] drm/hdcp: Add drm_hdcp_atomic_check()
From: Sean Paul This patch moves the hdcp atomic check from i915 to drm_hdcp so other drivers can use it. No functional changes, just cleaned up some of the code when moving it over. Acked-by: Jani Nikula Acked-by: Jani Nikula Reviewed-by: Rodrigo Vivi Reviewed-by: Abhinav Kumar Signed-off-by: Sean Paul Signed-off-by: Mark Yacoub Link: https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-2-s...@poorly.run #v1 Link: https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-2-s...@poorly.run #v2 Link: https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-2-s...@poorly.run #v3 Link: https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-2-s...@poorly.run #v4 Link: https://patchwork.freedesktop.org/patch/msgid/20220411204741.1074308-2-s...@poorly.run #v5 Changes in v2: -None Changes in v3: -None Changes in v4: -None Changes in v5: -None Changes in V6: -Rebase: move helper from drm_hdcp.c to drm_hdcp_helper.c --- drivers/gpu/drm/display/drm_hdcp_helper.c | 69 + drivers/gpu/drm/i915/display/intel_atomic.c | 4 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 47 -- drivers/gpu/drm/i915/display/intel_hdcp.h | 3 - include/drm/display/drm_hdcp_helper.h | 3 + 5 files changed, 74 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/display/drm_hdcp_helper.c b/drivers/gpu/drm/display/drm_hdcp_helper.c index e78999c72bd7..7d910523b05f 100644 --- a/drivers/gpu/drm/display/drm_hdcp_helper.c +++ b/drivers/gpu/drm/display/drm_hdcp_helper.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void drm_hdcp_print_ksv(const u8 *ksv) { @@ -419,3 +420,71 @@ void drm_hdcp_update_content_protection(struct drm_connector *connector, dev->mode_config.content_protection_property); } EXPORT_SYMBOL(drm_hdcp_update_content_protection); + +/** + * drm_hdcp_atomic_check - Helper for drivers to call during connector->atomic_check + * + * @state: pointer to the atomic state being checked + * @connector: drm_connector on which content protection state needs an update + * + * This function can be used by display drivers to perform an atomic check on the + * hdcp state elements. If hdcp state has changed, this function will set + * mode_changed on the crtc driving the connector so it can update its hardware + * to match the hdcp state. + */ +void drm_hdcp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *new_conn_state, *old_conn_state; + struct drm_crtc_state *new_crtc_state; + u64 old_hdcp, new_hdcp; + + old_conn_state = drm_atomic_get_old_connector_state(state, connector); + old_hdcp = old_conn_state->content_protection; + + new_conn_state = drm_atomic_get_new_connector_state(state, connector); + new_hdcp = new_conn_state->content_protection; + + if (!new_conn_state->crtc) { + /* +* If the connector is being disabled with CP enabled, mark it +* desired so it's re-enabled when the connector is brought back +*/ + if (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + return; + } + + new_crtc_state = + drm_atomic_get_new_crtc_state(state, new_conn_state->crtc); + /* + * Fix the HDCP uapi content protection state in case of modeset. + * FIXME: As per HDCP content protection property uapi doc, an uevent() + * need to be sent if there is transition from ENABLED->DESIRED. + */ + if (drm_atomic_crtc_needs_modeset(new_crtc_state) && + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp != DRM_MODE_CONTENT_PROTECTION_UNDESIRED)) + new_conn_state->content_protection = + DRM_MODE_CONTENT_PROTECTION_DESIRED; + + /* +* Nothing to do if content type is unchanged and one of: +* - state didn't change +* - HDCP was activated since the last commit +* - attempting to set to desired while already enabled +*/ + if (old_hdcp == new_hdcp || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED) || + (old_hdcp == DRM_MODE_CONTENT_PROTECTION_ENABLED && +new_hdcp == DRM_MODE_CONTENT_PROTECTION_DESIRED)) { + if (old_conn_state->hdcp_content_type == + new_conn_state->hdcp_content_type) + return; + } + + new_crtc_state->mode_changed = true; +} +EXPORT_SYMBOL(drm_hdcp_atomic_check); diff --git a/drivers/gpu/drm/i9
[Intel-gfx] [PATCH v6 00/10] drm/hdcp: Pull HDCP auth/exchange/check into helpers
From: Mark Yacoub Hello, I rebased this series which is authored by Sean Paul. A major rebase conflict was that drm/drm_hdcp was split to drm/display/drm_hdcp & drm/display/drm_hdcp_helper. Another major one was in msm dp where drm_connector was no longer tracked, but it's replaced by msm_dp_bridge to carry over its functionalities. The first 4 patches modify DRM. They've been reviewed. Patches 5-7 are intel-only. Only patch 7 hasn't been reviewed. Patches 8-10 are msm-only. Only patch 9 hasn't been reviewed. Thanks, Mark Sean Paul (10): drm/hdcp: Add drm_hdcp_atomic_check() drm/hdcp: Avoid changing crtc state in hdcp atomic check drm/hdcp: Update property value on content type and user changes drm/hdcp: Expand HDCP helper library for enable/disable/check drm/i915/hdcp: Consolidate HDCP setup/state cache drm/i915/hdcp: Retain hdcp_capable return codes drm/i915/hdcp: Use HDCP helpers for i915 dt-bindings: msm/dp: Add bindings for HDCP registers arm64: dts: qcom: sc7180: Add support for HDCP in dp-controller drm/msm: Implement HDCP 1.x using the new drm HDCP helpers .../bindings/display/msm/dp-controller.yaml |8 +- arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi |8 + drivers/gpu/drm/display/drm_hdcp_helper.c | 1202 + drivers/gpu/drm/i915/display/intel_atomic.c |8 +- drivers/gpu/drm/i915/display/intel_ddi.c | 32 +- .../drm/i915/display/intel_display_debugfs.c | 11 +- .../drm/i915/display/intel_display_types.h| 60 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 348 ++--- drivers/gpu/drm/i915/display/intel_dp_mst.c | 16 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 1028 +++--- drivers/gpu/drm/i915/display/intel_hdcp.h | 36 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 270 ++-- drivers/gpu/drm/msm/Kconfig |1 + drivers/gpu/drm/msm/Makefile |1 + drivers/gpu/drm/msm/dp/dp_debug.c | 48 +- drivers/gpu/drm/msm/dp/dp_debug.h |6 +- drivers/gpu/drm/msm/dp/dp_display.c | 52 +- drivers/gpu/drm/msm/dp/dp_display.h |5 + drivers/gpu/drm/msm/dp/dp_drm.c | 108 +- drivers/gpu/drm/msm/dp/dp_drm.h | 16 +- drivers/gpu/drm/msm/dp/dp_hdcp.c | 456 +++ drivers/gpu/drm/msm/dp/dp_hdcp.h | 29 + drivers/gpu/drm/msm/dp/dp_parser.c| 20 +- drivers/gpu/drm/msm/dp/dp_parser.h|4 + drivers/gpu/drm/msm/dp/dp_reg.h | 32 +- drivers/gpu/drm/msm/msm_atomic.c | 15 + include/drm/display/drm_hdcp.h| 168 ++- include/drm/display/drm_hdcp_helper.h | 33 +- 28 files changed, 2667 insertions(+), 1354 deletions(-) create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.c create mode 100644 drivers/gpu/drm/msm/dp/dp_hdcp.h -- 2.39.0.246.g2a6d74b583-goog
[Intel-gfx] [PATCH v5 2/3] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Resolves: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK Tested on Zork (amdgpu) and Jacuzzi (mediatek), volteer (TGL) v3: 1. Check for lut pointer inside drm_check_lut_size. v2: 1. Remove the rename to a parent commit. 2. Create a drm drm_check_lut_size instead of intel only function. v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 52 ++ drivers/gpu/drm/drm_color_mgmt.c | 19 drivers/gpu/drm/i915/display/intel_color.c | 32 ++--- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 3 ++ include/drm/drm_crtc.h | 11 + 6 files changed, 99 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..548e5d8221fb4 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,54 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (!new_crtc_state->color_mgmt_changed) + continue; + + if (drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_lut_size) || + drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_size)) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Expected %u/%u, got %u.\n", + crtc->gamma_lut_size, crtc->gamma_size, + drm_color_lut_size(new_crtc_state->gamma_lut)); + return -EINVAL; + } + + if (drm_check_lut_size(new_crtc_state->degamma_lut, + crtc->degamma_lut_size)) { + drm_dbg_state( + state->dev, + "Invalid Degamma LUT size. Expected %u, got %u.\n", + crtc->degamma_lut_size, + drm_color_lut_size( + new_crtc_state->degamma_lut)); + return -EINVAL; + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1022,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 16a07f84948f3..c85094223b535 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -166,6 +166,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; if (degamma_lut_size) { + crtc->degamma_lut_size = degamma_lut_size; drm_object_attach_property(&crtc->base, config->degamma_lut_property, 0); drm_object_attach_property(&crtc->base, @@ -178,6 +179,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
[Intel-gfx] [PATCH v5 1/3] drm: Move drm_color_lut_check implementation internal to intel_color
From: Mark Yacoub [Why] The tests of LUT_EQUAL_CHANNELS and LUT_NON_DECREASING are currently unique to i915 driver. Freeing up the function name for the more generic LUT checks to folllow Tested on Eldrid ChromeOS (TGL). v2: 1. Convert the enum to #define. 2. Add INTEL_COLOR_ prefix. v1: Stuff the test function from DRM to intel driver. Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_color_mgmt.c | 43 -- drivers/gpu/drm/i915/display/intel_color.c | 43 +++--- drivers/gpu/drm/i915/display/intel_color.h | 16 drivers/gpu/drm/i915/i915_pci.c| 28 -- include/drm/drm_color_mgmt.h | 27 -- 5 files changed, 71 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6c..16a07f84948f3 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -583,46 +583,3 @@ int drm_plane_create_color_properties(struct drm_plane *plane, return 0; } EXPORT_SYMBOL(drm_plane_create_color_properties); - -/** - * drm_color_lut_check - check validity of lookup table - * @lut: property blob containing LUT to check - * @tests: bitmask of tests to run - * - * Helper to check whether a userspace-provided lookup table is valid and - * satisfies hardware requirements. Drivers pass a bitmask indicating which of - * the tests in &drm_color_lut_tests should be performed. - * - * Returns 0 on success, -EINVAL on failure. - */ -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) -{ - const struct drm_color_lut *entry; - int i; - - if (!lut || !tests) - return 0; - - entry = lut->data; - for (i = 0; i < drm_color_lut_size(lut); i++) { - if (tests & DRM_COLOR_LUT_EQUAL_CHANNELS) { - if (entry[i].red != entry[i].blue || - entry[i].red != entry[i].green) { - DRM_DEBUG_KMS("All LUT entries must have equal r/g/b\n"); - return -EINVAL; - } - } - - if (i > 0 && tests & DRM_COLOR_LUT_NON_DECREASING) { - if (entry[i].red < entry[i - 1].red || - entry[i].green < entry[i - 1].green || - entry[i].blue < entry[i - 1].blue) { - DRM_DEBUG_KMS("LUT entries must never decrease.\n"); - return -EINVAL; - } - } - } - - return 0; -} -EXPORT_SYMBOL(drm_color_lut_check); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dab892d2251ba..1469871d21ff9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1279,13 +1279,46 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) return 0; } +static int test_luts(const struct drm_property_blob *lut, u32 tests) +{ + const struct drm_color_lut *entry; + int i; + + if (!lut || !tests) + return 0; + + entry = lut->data; + for (i = 0; i < drm_color_lut_size(lut); i++) { + if (tests & INTEL_COLOR_LUT_EQUAL_CHANNELS) { + if (entry[i].red != entry[i].blue || + entry[i].red != entry[i].green) { + DRM_DEBUG_KMS( + "All LUT entries must have equal r/g/b\n"); + return -EINVAL; + } + } + + if (i > 0 && tests & INTEL_COLOR_LUT_NON_DECREASING) { + if (entry[i].red < entry[i - 1].red || + entry[i].green < entry[i - 1].green || + entry[i].blue < entry[i - 1].blue) { + DRM_DEBUG_KMS( + "LUT entries must never decrease.\n"); + return -EINVAL; + } + } + } + + return 0; +} + static int check_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; + u32 gamma_channels_tests, degamma_channels_tests; /* Always allow legacy gamma LUT with no further checking. */ if (crtc_state_is_legacy_gamma(crtc_state)) @@ -1300,15
[Intel-gfx] [PATCH v4 2/3] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Resolves: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK Tested on Zork (amdgpu) and Jacuzzi (mediatek), volteer (TGL) v3: 1. Check for lut pointer inside drm_check_lut_size. v2: 1. Remove the rename to a parent commit. 2. Create a drm drm_check_lut_size instead of intel only function. v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 52 ++ drivers/gpu/drm/drm_color_mgmt.c | 19 drivers/gpu/drm/i915/display/intel_color.c | 32 ++--- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 3 ++ include/drm/drm_crtc.h | 11 + 6 files changed, 99 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..548e5d8221fb4 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,54 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (!new_crtc_state->color_mgmt_changed) + continue; + + if (drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_lut_size) || + drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_size)) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Expected %u/%u, got %u.\n", + crtc->gamma_lut_size, crtc->gamma_size, + drm_color_lut_size(new_crtc_state->gamma_lut)); + return -EINVAL; + } + + if (drm_check_lut_size(new_crtc_state->degamma_lut, + crtc->degamma_lut_size)) { + drm_dbg_state( + state->dev, + "Invalid Degamma LUT size. Expected %u, got %u.\n", + crtc->degamma_lut_size, + drm_color_lut_size( + new_crtc_state->degamma_lut)); + return -EINVAL; + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1022,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 16a07f84948f3..c85094223b535 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -166,6 +166,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; if (degamma_lut_size) { + crtc->degamma_lut_size = degamma_lut_size; drm_object_attach_property(&crtc->base, config->degamma_lut_property, 0); drm_object_attach_property(&crtc->base, @@ -178,6 +179,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc,
[Intel-gfx] [PATCH v4 1/3] drm: Move drm_color_lut_check implementation internal to intel_color
From: Mark Yacoub [Why] The tests of LUT_EQUAL_CHANNELS and LUT_NON_DECREASING are currently unique to i915 driver. Freeing up the function name for the more generic LUT checks to folllow Tested on Eldrid ChromeOS (TGL). v1: Stuff the test function from DRM to intel driver. Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_color_mgmt.c | 43 -- drivers/gpu/drm/i915/display/intel_color.c | 43 +++--- drivers/gpu/drm/i915/display/intel_color.h | 27 ++ drivers/gpu/drm/i915/i915_pci.c| 27 -- include/drm/drm_color_mgmt.h | 27 -- 5 files changed, 81 insertions(+), 86 deletions(-) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6c..16a07f84948f3 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -583,46 +583,3 @@ int drm_plane_create_color_properties(struct drm_plane *plane, return 0; } EXPORT_SYMBOL(drm_plane_create_color_properties); - -/** - * drm_color_lut_check - check validity of lookup table - * @lut: property blob containing LUT to check - * @tests: bitmask of tests to run - * - * Helper to check whether a userspace-provided lookup table is valid and - * satisfies hardware requirements. Drivers pass a bitmask indicating which of - * the tests in &drm_color_lut_tests should be performed. - * - * Returns 0 on success, -EINVAL on failure. - */ -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) -{ - const struct drm_color_lut *entry; - int i; - - if (!lut || !tests) - return 0; - - entry = lut->data; - for (i = 0; i < drm_color_lut_size(lut); i++) { - if (tests & DRM_COLOR_LUT_EQUAL_CHANNELS) { - if (entry[i].red != entry[i].blue || - entry[i].red != entry[i].green) { - DRM_DEBUG_KMS("All LUT entries must have equal r/g/b\n"); - return -EINVAL; - } - } - - if (i > 0 && tests & DRM_COLOR_LUT_NON_DECREASING) { - if (entry[i].red < entry[i - 1].red || - entry[i].green < entry[i - 1].green || - entry[i].blue < entry[i - 1].blue) { - DRM_DEBUG_KMS("LUT entries must never decrease.\n"); - return -EINVAL; - } - } - } - - return 0; -} -EXPORT_SYMBOL(drm_color_lut_check); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dab892d2251ba..bde98a155c9f3 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1279,13 +1279,46 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected) return 0; } +static int test_luts(const struct drm_property_blob *lut, u32 tests) +{ + const struct drm_color_lut *entry; + int i; + + if (!lut || !tests) + return 0; + + entry = lut->data; + for (i = 0; i < drm_color_lut_size(lut); i++) { + if (tests & LUT_EQUAL_CHANNELS) { + if (entry[i].red != entry[i].blue || + entry[i].red != entry[i].green) { + DRM_DEBUG_KMS( + "All LUT entries must have equal r/g/b\n"); + return -EINVAL; + } + } + + if (i > 0 && tests & LUT_NON_DECREASING) { + if (entry[i].red < entry[i - 1].red || + entry[i].green < entry[i - 1].green || + entry[i].blue < entry[i - 1].blue) { + DRM_DEBUG_KMS( + "LUT entries must never decrease.\n"); + return -EINVAL; + } + } + } + + return 0; +} + static int check_luts(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; + u32 gamma_channels_tests, degamma_channels_tests; /* Always allow legacy gamma LUT with no further checking. */ if (crtc_state_is_legacy_gamma(crtc_state)) @@ -1300,15 +1333,15 @@ static int check_luts(const struct intel_crtc_state *crtc_state) dega
Re: [Intel-gfx] [PATCH v3 1/3] drm: Rename lut check functions to lut channel checks
On Thu, Oct 28, 2021 at 8:42 PM Sean Paul wrote: > > On Tue, Oct 26, 2021 at 03:21:00PM -0400, Mark Yacoub wrote: > > From: Mark Yacoub > > > > [Why] > > This function and enum do not do generic checking on the luts but they > > test color channels in the LUTs. > > I'm not sure there's anything inherently specific to channels, it seems like > one could add a new test to reflect a HW limitation and it would fit pretty > well > in the lut check function. I wonder if it would be better to expose the types > of > tests required by the crtc such that the atomic_check could also do the test? > So the tests of the color are pretty unique to intel devices, no other device is using it so I didn't think it adds a lot of benefit adding it to the lut check. However, it's still in DRM because technically it can be supported by any driver. But once it is, the driver will have to expose the tests it wants so we can check it in atomic_check. but given that no one does expose any test but intel, i just left it only used by them. > Sean > > > Keeping the name explicit as more generic LUT checks will follow. > > > > Tested on Eldrid ChromeOS (TGL). > > > > Signed-off-by: Mark Yacoub > > --- > > drivers/gpu/drm/drm_color_mgmt.c | 12 ++-- > > drivers/gpu/drm/i915/display/intel_color.c | 10 +- > > include/drm/drm_color_mgmt.h | 7 --- > > 3 files changed, 15 insertions(+), 14 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_color_mgmt.c > > b/drivers/gpu/drm/drm_color_mgmt.c > > index bb14f488c8f6c..6f4e04746d90f 100644 > > --- a/drivers/gpu/drm/drm_color_mgmt.c > > +++ b/drivers/gpu/drm/drm_color_mgmt.c > > @@ -585,17 +585,17 @@ int drm_plane_create_color_properties(struct > > drm_plane *plane, > > EXPORT_SYMBOL(drm_plane_create_color_properties); > > > > /** > > - * drm_color_lut_check - check validity of lookup table > > + * drm_color_lut_channels_check - check validity of the channels in the > > lookup table > > * @lut: property blob containing LUT to check > > * @tests: bitmask of tests to run > > * > > - * Helper to check whether a userspace-provided lookup table is valid and > > - * satisfies hardware requirements. Drivers pass a bitmask indicating > > which of > > - * the tests in &drm_color_lut_tests should be performed. > > + * Helper to check whether each color channel of userspace-provided lookup > > table is valid and > > + * satisfies hardware requirements. Drivers pass a bitmask indicating > > which of in > > + * &drm_color_lut_channels_tests should be performed. > > * > > * Returns 0 on success, -EINVAL on failure. > > */ > > -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) > > +int drm_color_lut_channels_check(const struct drm_property_blob *lut, u32 > > tests) > > { > > const struct drm_color_lut *entry; > > int i; > > @@ -625,4 +625,4 @@ int drm_color_lut_check(const struct drm_property_blob > > *lut, u32 tests) > > > > return 0; > > } > > -EXPORT_SYMBOL(drm_color_lut_check); > > +EXPORT_SYMBOL(drm_color_lut_channels_check); > > diff --git a/drivers/gpu/drm/i915/display/intel_color.c > > b/drivers/gpu/drm/i915/display/intel_color.c > > index dab892d2251ba..4bb1bc76c4de9 100644 > > --- a/drivers/gpu/drm/i915/display/intel_color.c > > +++ b/drivers/gpu/drm/i915/display/intel_color.c > > @@ -1285,7 +1285,7 @@ static int check_luts(const struct intel_crtc_state > > *crtc_state) > > const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; > > const struct drm_property_blob *degamma_lut = > > crtc_state->hw.degamma_lut; > > int gamma_length, degamma_length; > > - u32 gamma_tests, degamma_tests; > > + u32 gamma_channels_tests, degamma_channels_tests; > > > > /* Always allow legacy gamma LUT with no further checking. */ > > if (crtc_state_is_legacy_gamma(crtc_state)) > > @@ -1300,15 +1300,15 @@ static int check_luts(const struct intel_crtc_state > > *crtc_state) > > > > degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size; > > gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size; > > - degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; > > - gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; > > + degamma_channels_tests = > > INTEL_INFO(dev_priv)->color.degamma_lut_tests; > > + gamma_channels_tes
Re: [Intel-gfx] [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
new patch: https://patchwork.freedesktop.org/series/96314/ On Tue, Oct 26, 2021 at 3:24 PM Mark Yacoub wrote: > > On Tue, Oct 26, 2021 at 8:02 AM Paul Menzel wrote: > > > > Dear Mark, > > > > > > Thank you for your patch. > > > > On 13.10.21 20:12, Mark Yacoub wrote: > > > From: Mark Yacoub > > > > > > [Why] > > > 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma > > > or Degamma props in the new CRTC state, allowing any invalid size to > > > be passed on. > > > 2. Each driver has its own LUT size, which could also be different for > > > legacy users. > > > > How can the problem be reproduced? > It was caught using igt@kms_color@pipe-A-invalid-gamma-lut-sizes. > it validates that drivers will only LUTs of their expected size not > any random (smaller or larger) number. > > > > > [How] > > > 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes > > > assigned by the driver when it's initializing its color and CTM > > > management. > > > 2. Create drm_atomic_helper_check_crtc which is called by > > > drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that > > > they match the sizes in the new CRTC state. > > > 3. Rename older lut checks that test for the color channels to indicate > > > it's a channel check. It's not included in drm_atomic_helper_check_crtc > > > as it's hardware specific and is to be called by the driver. > > > 4. As the LUT size check now happens in drm_atomic_helper_check, remove > > > the lut check in intel_color.c > > > > > > Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK > > > > If I am not mistaken, the Fixes tag is used for commits I believe. Maybe > > use Resolves or something similar? > fixed! > > > > > Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) > > > > Please add a space before the (. my apologies i missed this. I'll update it if another version is needed or if the committer can do it for me when they apply it. > > > > How did you test this? > smoke test on both MTK and TGL devices along with running > igt@kms_color on both devices. > > > > > v1: > > > 1. Fix typos > > > 2. Remove the LUT size check from intel driver > > > 3. Rename old LUT check to indicate it's a channel change > > > > > > Signed-off-by: Mark Yacoub > > > --- > > > drivers/gpu/drm/drm_atomic_helper.c| 60 ++ > > > drivers/gpu/drm/drm_color_mgmt.c | 14 ++--- > > > drivers/gpu/drm/i915/display/intel_color.c | 14 ++--- > > > include/drm/drm_atomic_helper.h| 1 + > > > include/drm/drm_color_mgmt.h | 7 +-- > > > include/drm/drm_crtc.h | 11 > > > 6 files changed, 89 insertions(+), 18 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > > > b/drivers/gpu/drm/drm_atomic_helper.c > > > index bc3487964fb5e..5feb2ad0209c3 100644 > > > --- a/drivers/gpu/drm/drm_atomic_helper.c > > > +++ b/drivers/gpu/drm/drm_atomic_helper.c > > > @@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device > > > *dev, > > > } > > > EXPORT_SYMBOL(drm_atomic_helper_check_planes); > > > > > > +/** > > > + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes > > > + * @state: the driver state object > > > + * > > > + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if > > > the new > > > + * state holds them. > > > + * > > > + * RETURNS: > > > + * Zero for success or -errno > > > + */ > > > +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) > > > +{ > > > + struct drm_crtc *crtc; > > > + struct drm_crtc_state *new_crtc_state; > > > + int i; > > > + > > > + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { > > > + if (new_crtc_state->color_mgmt_changed && > > > + new_crtc_state->gamma_lut) { > > > + uint64_t supported_lut_size = crtc->gamma_lut_size; > > > + uint32_t supported_legacy_lut_size = > > > crtc->gamma_size; > > > + uint32_t new_state_lut_size = > > > + > > > drm_c
Re: [Intel-gfx] [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
On Mon, Oct 25, 2021 at 9:26 PM Sean Paul wrote: > > On Wed, Oct 13, 2021 at 02:12:20PM -0400, Mark Yacoub wrote: > > From: Mark Yacoub > > > > [Why] > > 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma > > or Degamma props in the new CRTC state, allowing any invalid size to > > be passed on. > > 2. Each driver has its own LUT size, which could also be different for > > legacy users. > > > > [How] > > 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes > > assigned by the driver when it's initializing its color and CTM > > management. > > 2. Create drm_atomic_helper_check_crtc which is called by > > drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that > > they match the sizes in the new CRTC state. > > 3. Rename older lut checks that test for the color channels to indicate > > it's a channel check. It's not included in drm_atomic_helper_check_crtc > > as it's hardware specific and is to be called by the driver. > > 4. As the LUT size check now happens in drm_atomic_helper_check, remove > > the lut check in intel_color.c > > I'd probably split the rename out from the crtc check since they're only > tangentially related. done. > > > > > Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK > > Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) > > > > v1: > > 1. Fix typos > > 2. Remove the LUT size check from intel driver > > 3. Rename old LUT check to indicate it's a channel change > > > > Signed-off-by: Mark Yacoub > > --- > > drivers/gpu/drm/drm_atomic_helper.c| 60 ++ > > drivers/gpu/drm/drm_color_mgmt.c | 14 ++--- > > drivers/gpu/drm/i915/display/intel_color.c | 14 ++--- > > include/drm/drm_atomic_helper.h| 1 + > > include/drm/drm_color_mgmt.h | 7 +-- > > include/drm/drm_crtc.h | 11 > > 6 files changed, 89 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > > b/drivers/gpu/drm/drm_atomic_helper.c > > index bc3487964fb5e..5feb2ad0209c3 100644 > > --- a/drivers/gpu/drm/drm_atomic_helper.c > > +++ b/drivers/gpu/drm/drm_atomic_helper.c > > @@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device *dev, > > } > > EXPORT_SYMBOL(drm_atomic_helper_check_planes); > > > > +/** > > + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes > > + * @state: the driver state object > > + * > > + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the > > new > > + * state holds them. > > + * > > + * RETURNS: > > + * Zero for success or -errno > > + */ > > +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) > > +{ > > + struct drm_crtc *crtc; > > + struct drm_crtc_state *new_crtc_state; > > + int i; > > + > > + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { > > + if (new_crtc_state->color_mgmt_changed && > > + new_crtc_state->gamma_lut) { > > + uint64_t supported_lut_size = crtc->gamma_lut_size; > > + uint32_t supported_legacy_lut_size = crtc->gamma_size; > > + uint32_t new_state_lut_size = > > + drm_color_lut_size(new_crtc_state->gamma_lut); > > + > > + if (new_state_lut_size != supported_lut_size && > > + new_state_lut_size != supported_legacy_lut_size) { > > + drm_dbg_state( > > + state->dev, > > + "Invalid Gamma LUT size. Should be %u > > (or %u for legacy) but got %u.\n", > > + supported_lut_size, > > + supported_legacy_lut_size, > > + new_state_lut_size); > > + return -EINVAL; > > + } > > + } > > + > > + if (new_crtc_state->color_mgmt_changed && > > + new_crtc_state->degamma_lut) { > > + uint32_t new_state_lut_size = > > + > > drm_color_lut_size(new_crtc_state->degamma_lut); > > + uint64_t supported_lut_size = crtc->d
Re: [Intel-gfx] [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
On Tue, Oct 26, 2021 at 8:02 AM Paul Menzel wrote: > > Dear Mark, > > > Thank you for your patch. > > On 13.10.21 20:12, Mark Yacoub wrote: > > From: Mark Yacoub > > > > [Why] > > 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma > > or Degamma props in the new CRTC state, allowing any invalid size to > > be passed on. > > 2. Each driver has its own LUT size, which could also be different for > > legacy users. > > How can the problem be reproduced? It was caught using igt@kms_color@pipe-A-invalid-gamma-lut-sizes. it validates that drivers will only LUTs of their expected size not any random (smaller or larger) number. > > > [How] > > 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes > > assigned by the driver when it's initializing its color and CTM > > management. > > 2. Create drm_atomic_helper_check_crtc which is called by > > drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that > > they match the sizes in the new CRTC state. > > 3. Rename older lut checks that test for the color channels to indicate > > it's a channel check. It's not included in drm_atomic_helper_check_crtc > > as it's hardware specific and is to be called by the driver. > > 4. As the LUT size check now happens in drm_atomic_helper_check, remove > > the lut check in intel_color.c > > > > Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK > > If I am not mistaken, the Fixes tag is used for commits I believe. Maybe > use Resolves or something similar? fixed! > > > Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) > > Please add a space before the (. > > How did you test this? smoke test on both MTK and TGL devices along with running igt@kms_color on both devices. > > > v1: > > 1. Fix typos > > 2. Remove the LUT size check from intel driver > > 3. Rename old LUT check to indicate it's a channel change > > > > Signed-off-by: Mark Yacoub > > --- > > drivers/gpu/drm/drm_atomic_helper.c| 60 ++ > > drivers/gpu/drm/drm_color_mgmt.c | 14 ++--- > > drivers/gpu/drm/i915/display/intel_color.c | 14 ++--- > > include/drm/drm_atomic_helper.h| 1 + > > include/drm/drm_color_mgmt.h | 7 +-- > > include/drm/drm_crtc.h | 11 > > 6 files changed, 89 insertions(+), 18 deletions(-) > > > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > > b/drivers/gpu/drm/drm_atomic_helper.c > > index bc3487964fb5e..5feb2ad0209c3 100644 > > --- a/drivers/gpu/drm/drm_atomic_helper.c > > +++ b/drivers/gpu/drm/drm_atomic_helper.c > > @@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device *dev, > > } > > EXPORT_SYMBOL(drm_atomic_helper_check_planes); > > > > +/** > > + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes > > + * @state: the driver state object > > + * > > + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the > > new > > + * state holds them. > > + * > > + * RETURNS: > > + * Zero for success or -errno > > + */ > > +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) > > +{ > > + struct drm_crtc *crtc; > > + struct drm_crtc_state *new_crtc_state; > > + int i; > > + > > + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { > > + if (new_crtc_state->color_mgmt_changed && > > + new_crtc_state->gamma_lut) { > > + uint64_t supported_lut_size = crtc->gamma_lut_size; > > + uint32_t supported_legacy_lut_size = crtc->gamma_size; > > + uint32_t new_state_lut_size = > > + drm_color_lut_size(new_crtc_state->gamma_lut); > > + > > + if (new_state_lut_size != supported_lut_size && > > + new_state_lut_size != supported_legacy_lut_size) { > > + drm_dbg_state( > > + state->dev, > > + "Invalid Gamma LUT size. Should be %u > > (or %u for legacy) but got %u.\n", > > + supported_lut_size, > > + supported_legacy_lut_size, > > + new_state_lut_size); > > + return -EINVAL; > > +
[Intel-gfx] [PATCH v3 2/3] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Resolves: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) v2: 1. Remove the rename to a parent commit. 2. Create a drm drm_check_lut_size instead of intel only function. v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 56 ++ drivers/gpu/drm/drm_color_mgmt.c | 2 + drivers/gpu/drm/i915/display/intel_color.c | 39 --- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 13 + include/drm/drm_crtc.h | 11 + 6 files changed, 102 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..c565b3516cce9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,58 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->gamma_lut) { + if (drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_lut_size) || + drm_check_lut_size(new_crtc_state->gamma_lut, + crtc->gamma_size)) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + crtc->gamma_lut_size, crtc->gamma_size, + drm_color_lut_size( + new_crtc_state->gamma_lut)); + return -EINVAL; + } + } + + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->degamma_lut) { + if (drm_check_lut_size(new_crtc_state->degamma_lut, + crtc->degamma_lut_size)) { + drm_dbg_state( + state->dev, + "Invalid DeGamma LUT size. Should be %u but got %u.\n", + crtc->degamma_lut_size, + drm_color_lut_size( + new_crtc_state->degamma_lut)); + return -EINVAL; + } + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1026,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 6f4e04746d90f..6bb59645a75bc 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -166,6 +166,7 @@ void drm_crtc_enable_color_mgmt(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; if (degamma_lut_
[Intel-gfx] [PATCH v3 1/3] drm: Rename lut check functions to lut channel checks
From: Mark Yacoub [Why] This function and enum do not do generic checking on the luts but they test color channels in the LUTs. Keeping the name explicit as more generic LUT checks will follow. Tested on Eldrid ChromeOS (TGL). Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_color_mgmt.c | 12 ++-- drivers/gpu/drm/i915/display/intel_color.c | 10 +- include/drm/drm_color_mgmt.h | 7 --- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6c..6f4e04746d90f 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -585,17 +585,17 @@ int drm_plane_create_color_properties(struct drm_plane *plane, EXPORT_SYMBOL(drm_plane_create_color_properties); /** - * drm_color_lut_check - check validity of lookup table + * drm_color_lut_channels_check - check validity of the channels in the lookup table * @lut: property blob containing LUT to check * @tests: bitmask of tests to run * - * Helper to check whether a userspace-provided lookup table is valid and - * satisfies hardware requirements. Drivers pass a bitmask indicating which of - * the tests in &drm_color_lut_tests should be performed. + * Helper to check whether each color channel of userspace-provided lookup table is valid and + * satisfies hardware requirements. Drivers pass a bitmask indicating which of in + * &drm_color_lut_channels_tests should be performed. * * Returns 0 on success, -EINVAL on failure. */ -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) +int drm_color_lut_channels_check(const struct drm_property_blob *lut, u32 tests) { const struct drm_color_lut *entry; int i; @@ -625,4 +625,4 @@ int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests) return 0; } -EXPORT_SYMBOL(drm_color_lut_check); +EXPORT_SYMBOL(drm_color_lut_channels_check); diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index dab892d2251ba..4bb1bc76c4de9 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -1285,7 +1285,7 @@ static int check_luts(const struct intel_crtc_state *crtc_state) const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut; const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut; int gamma_length, degamma_length; - u32 gamma_tests, degamma_tests; + u32 gamma_channels_tests, degamma_channels_tests; /* Always allow legacy gamma LUT with no further checking. */ if (crtc_state_is_legacy_gamma(crtc_state)) @@ -1300,15 +1300,15 @@ static int check_luts(const struct intel_crtc_state *crtc_state) degamma_length = INTEL_INFO(dev_priv)->color.degamma_lut_size; gamma_length = INTEL_INFO(dev_priv)->color.gamma_lut_size; - degamma_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; - gamma_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; + degamma_channels_tests = INTEL_INFO(dev_priv)->color.degamma_lut_tests; + gamma_channels_tests = INTEL_INFO(dev_priv)->color.gamma_lut_tests; if (check_lut_size(degamma_lut, degamma_length) || check_lut_size(gamma_lut, gamma_length)) return -EINVAL; - if (drm_color_lut_check(degamma_lut, degamma_tests) || - drm_color_lut_check(gamma_lut, gamma_tests)) + if (drm_color_lut_channels_check(degamma_lut, degamma_channels_tests) || + drm_color_lut_channels_check(gamma_lut, gamma_channels_tests)) return -EINVAL; return 0; diff --git a/include/drm/drm_color_mgmt.h b/include/drm/drm_color_mgmt.h index 81c298488b0c8..cb1bf361ad3e3 100644 --- a/include/drm/drm_color_mgmt.h +++ b/include/drm/drm_color_mgmt.h @@ -94,12 +94,12 @@ int drm_plane_create_color_properties(struct drm_plane *plane, enum drm_color_range default_range); /** - * enum drm_color_lut_tests - hw-specific LUT tests to perform + * enum drm_color_lut_channels_tests - hw-specific LUT tests to perform * * The drm_color_lut_check() function takes a bitmask of the values here to * determine which tests to apply to a userspace-provided LUT. */ -enum drm_color_lut_tests { +enum drm_color_lut_channels_tests { /** * @DRM_COLOR_LUT_EQUAL_CHANNELS: * @@ -119,5 +119,6 @@ enum drm_color_lut_tests { DRM_COLOR_LUT_NON_DECREASING = BIT(1), }; -int drm_color_lut_check(const struct drm_property_blob *lut, u32 tests); +int drm_color_lut_channels_check(const struct drm_property_blob *lut, +u32 tests); #endif -- 2.33.0.1079.g6e70778dc9-goog
[Intel-gfx] [PATCH 2/2] amd/amdgpu_dm: Verify Gamma and Degamma LUT sizes using DRM Core check
From: Mark Yacoub [Why] drm_atomic_helper_check_crtc now verifies both legacy and non-legacy LUT sizes. There is no need to check it within amdgpu_dm_atomic_check. [How] Remove the local call to verify LUT sizes and use DRM Core function instead. Tested on ChromeOS Zork. v1: Remove amdgpu_dm_verify_lut_sizes everywhere. Signed-off-by: Mark Yacoub --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 - .../amd/display/amdgpu_dm/amdgpu_dm_color.c | 35 --- 3 files changed, 4 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index f74663b6b046e..47f8de1cfc3a5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -10244,6 +10244,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } #endif + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); @@ -10253,10 +10257,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, dm_old_crtc_state->dsc_force_changed == false) continue; - ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); - if (ret) - goto fail; - if (!new_crtc_state->enable) continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index fcb9c4a629c32..22730e5542092 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -617,7 +617,6 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 void amdgpu_dm_init_color_mod(void); -int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index a022e5bb30a5c..319f8a8a89835 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -284,37 +284,6 @@ static int __set_input_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } -/** - * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of - * the expected size. - * Returns 0 on success. - */ -int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) -{ - const struct drm_color_lut *lut = NULL; - uint32_t size = 0; - - lut = __extract_blob_lut(crtc_state->degamma_lut, &size); - if (lut && size != MAX_COLOR_LUT_ENTRIES) { - DRM_DEBUG_DRIVER( - "Invalid Degamma LUT size. Should be %u but got %u.\n", - MAX_COLOR_LUT_ENTRIES, size); - return -EINVAL; - } - - lut = __extract_blob_lut(crtc_state->gamma_lut, &size); - if (lut && size != MAX_COLOR_LUT_ENTRIES && - size != MAX_COLOR_LEGACY_LUT_ENTRIES) { - DRM_DEBUG_DRIVER( - "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", - MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, - size); - return -EINVAL; - } - - return 0; -} - /** * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. * @crtc: amdgpu_dm crtc state @@ -348,10 +317,6 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) bool is_legacy; int r; - r = amdgpu_dm_verify_lut_sizes(&crtc->base); - if (r) - return r; - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); -- 2.33.0.882.g93a45727a2-goog
[Intel-gfx] [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
From: Mark Yacoub [Why] 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma or Degamma props in the new CRTC state, allowing any invalid size to be passed on. 2. Each driver has its own LUT size, which could also be different for legacy users. [How] 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes assigned by the driver when it's initializing its color and CTM management. 2. Create drm_atomic_helper_check_crtc which is called by drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that they match the sizes in the new CRTC state. 3. Rename older lut checks that test for the color channels to indicate it's a channel check. It's not included in drm_atomic_helper_check_crtc as it's hardware specific and is to be called by the driver. 4. As the LUT size check now happens in drm_atomic_helper_check, remove the lut check in intel_color.c Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK Tested on Zork(amdgpu) and Jacuzzi(mediatek), volteer(TGL) v1: 1. Fix typos 2. Remove the LUT size check from intel driver 3. Rename old LUT check to indicate it's a channel change Signed-off-by: Mark Yacoub --- drivers/gpu/drm/drm_atomic_helper.c| 60 ++ drivers/gpu/drm/drm_color_mgmt.c | 14 ++--- drivers/gpu/drm/i915/display/intel_color.c | 14 ++--- include/drm/drm_atomic_helper.h| 1 + include/drm/drm_color_mgmt.h | 7 +-- include/drm/drm_crtc.h | 11 6 files changed, 89 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index bc3487964fb5e..5feb2ad0209c3 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -929,6 +929,62 @@ drm_atomic_helper_check_planes(struct drm_device *dev, } EXPORT_SYMBOL(drm_atomic_helper_check_planes); +/** + * drm_atomic_helper_check_crtcs - validate state object for CRTC changes + * @state: the driver state object + * + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new + * state holds them. + * + * RETURNS: + * Zero for success or -errno + */ +int drm_atomic_helper_check_crtcs(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int i; + + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->gamma_lut) { + uint64_t supported_lut_size = crtc->gamma_lut_size; + uint32_t supported_legacy_lut_size = crtc->gamma_size; + uint32_t new_state_lut_size = + drm_color_lut_size(new_crtc_state->gamma_lut); + + if (new_state_lut_size != supported_lut_size && + new_state_lut_size != supported_legacy_lut_size) { + drm_dbg_state( + state->dev, + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + supported_lut_size, + supported_legacy_lut_size, + new_state_lut_size); + return -EINVAL; + } + } + + if (new_crtc_state->color_mgmt_changed && + new_crtc_state->degamma_lut) { + uint32_t new_state_lut_size = + drm_color_lut_size(new_crtc_state->degamma_lut); + uint64_t supported_lut_size = crtc->degamma_lut_size; + + if (new_state_lut_size != supported_lut_size) { + drm_dbg_state( + state->dev, + "Invalid Degamma LUT size. Should be %u but got %u.\n", + supported_lut_size, new_state_lut_size); + return -EINVAL; + } + } + } + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_check_crtcs); + /** * drm_atomic_helper_check - validate state object * @dev: DRM device @@ -974,6 +1030,10 @@ int drm_atomic_helper_check(struct drm_device *dev, if (ret) return ret; + ret = drm_atomic_helper_check_crtcs(state); + if (ret) + return ret; + if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index bb14f488c8f6c..e5b820ce823bf 100644 --- a/drivers/gpu/drm/d
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_dp_dsc: Avoid SIGSEGV when release DRM connector.
On Fri, Jun 4, 2021 at 2:48 PM Mark Yacoub wrote: > > On Mon, May 31, 2021 at 11:34 AM Lee Shawn C wrote: > > > > Got SIGSEGV fault while running kms_dp_dsc test but did not > > connect DP DSC capable monitor on eDP/DP port. This test daemon > > should "SKIP" test without any problem. We found kms_dp_dsc > > can't get proper drmModeConnector and caused this SIGSEGV fault > > when release it. Make sure drmModeConnector is available before > > free it can avoid this issue. > > > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat). Tested on ChromeOS AMD (Zork) with Kernel 5.4 > Tested-by: Mark Yacoub > > Signed-off-by: Lee Shawn C > > --- > > tests/kms_dp_dsc.c | 5 +++-- > > 1 file changed, 3 insertions(+), 2 deletions(-) > > > > diff --git a/tests/kms_dp_dsc.c b/tests/kms_dp_dsc.c > > index 2446fd82bba3..ea7c9f4f72ce 100644 > > --- a/tests/kms_dp_dsc.c > > +++ b/tests/kms_dp_dsc.c > > @@ -262,7 +262,7 @@ igt_main > > data_t data = {}; > > igt_output_t *output; > > drmModeRes *res; > > - drmModeConnector *connector; > > + drmModeConnector *connector = NULL; > > int i, test_conn_cnt, test_cnt; > > int tests[] = {DRM_MODE_CONNECTOR_eDP, > > DRM_MODE_CONNECTOR_DisplayPort}; > > > > @@ -311,7 +311,8 @@ igt_main > > } > > > > igt_fixture { > > - drmModeFreeConnector(connector); > > + if (connector) > > + drmModeFreeConnector(connector); > > drmModeFreeResources(res); > > close(data.debugfs_fd); > > close(data.drm_fd); > > -- > > 2.17.1 > > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [igt-dev] [PATCH i-g-t] [RFC] tests/kms_prime: Aligned pitch to 64 byte for Intel platforms
On Mon, May 31, 2021 at 10:47 AM Srinivas, Vidya wrote: > > Hello Ville, > > Thank you very much. > Before reaching our i915's i915_gem_dumb_create, it goes to > vgem_gem_dumb_create for kms_prime. > > The pitch gets calculated there and it is not 64 byte aligned. Due to this, > intel_framebuffer_init reports "pitch must be 64 byte aligned" > and framebuffer creation fails. I tried submitting vgem patch where 64 byte > alignment can be done in vgem_gem_dumb_create and that also > passes. But we did not get approval yet as few of them felt, vgem is generic > and other platforms might fail if we do 64 byte alignment there. > > Kindly suggest. Thanks a lot. > > Regards > Vidya > > -Original Message- > From: Ville Syrjälä > Sent: Monday, May 31, 2021 7:48 PM > To: Srinivas, Vidya > Cc: intel-gfx@lists.freedesktop.org; igt-...@lists.freedesktop.org; Lin, > Charlton > Subject: Re: [igt-dev] [PATCH i-g-t] [RFC] tests/kms_prime: Aligned pitch to > 64 byte for Intel platforms > > On Fri, May 28, 2021 at 10:04:03AM +0530, Vidya Srinivas wrote: > > For Intel platforms, pitch needs to be 64 byte aligned. > > Kernel code vgem_gem_dumb_create which is platform generic code doesnt > > do the alignment. This causes frame buffer creation to fail on Intel > > platforms where the pitch is not 64 byte aligned. > > > > tests: test run on Intel platforms with panel resolution 1366x768 > > Tested on ChromeOS on JSL (Drawlat). Tested-by: Mark Yacoub > > Signed-off-by: Vidya Srinivas > > --- > > tests/kms_prime.c | 5 - > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > diff --git a/tests/kms_prime.c b/tests/kms_prime.c index > > 8cb2ca2a9dc3..fdc941fe8100 100644 > > --- a/tests/kms_prime.c > > +++ b/tests/kms_prime.c > > @@ -51,6 +51,8 @@ static struct { > > { .r = 1.0, .g = 0.0, .b = 0.0, .color = 0x }, }; > > > > +bool check_platform; I think we can do a more precise name to indicate which platform. Something like is_intel_device or is_i915 would be more appropriate. alternatively, we can drop the boolean and just do the check when needed. So it would look something like + is_i915_device(fd) ? ALIGN(scratch->width, 64) : scratch->width, > > + > > IGT_TEST_DESCRIPTION("Prime tests, focusing on KMS side"); > > > > static bool has_prime_import(int fd) > > @@ -101,7 +103,7 @@ static void prepare_scratch(int exporter_fd, struct > > dumb_bo *scratch, > > scratch->bpp = 32; > > > > scratch->handle = kmstest_dumb_create(exporter_fd, > > - scratch->width, > > + check_platform? ALIGN(scratch->width, 64): > > scratch->width, > > The dumb_create ioctl already does this for us. > > > scratch->height, > > scratch->bpp, > > &scratch->pitch, > > @@ -262,6 +264,7 @@ igt_main > > > > /* ANY = anything that is not VGEM */ > > first_fd = __drm_open_driver_another(0, DRIVER_ANY | > > DRIVER_VGEM); > > + check_platform = is_i915_device(first_fd); > > igt_require(first_fd >= 0); > > > > second_fd = __drm_open_driver_another(1, DRIVER_ANY | > > DRIVER_VGEM); > > -- > > 2.7.4 > > > > ___ > > igt-dev mailing list > > igt-...@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/igt-dev > > -- > Ville Syrjälä > Intel > ___ > igt-dev mailing list > igt-...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/igt-dev ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] [RFC] tests/kms_big_fb: Wait for vblank before collecting CRC
On Fri, May 28, 2021 at 12:36 AM Vidya Srinivas wrote: > > Without wait for vblank, CRC mismatch is seen > between big and small CRC on few Gen11 systems. > Tested on ChromeOS on JSL (Drawlat). Tested-by: Mark Yacoub > Signed-off-by: Vidya Srinivas > --- > tests/kms_big_fb.c | 6 -- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/tests/kms_big_fb.c b/tests/kms_big_fb.c > index b35727a09bd0..f90363c3beb2 100644 > --- a/tests/kms_big_fb.c > +++ b/tests/kms_big_fb.c > @@ -254,6 +254,7 @@ static void unset_lut(data_t *data) > static bool test_plane(data_t *data) > { > igt_plane_t *plane = data->plane; > + igt_display_t *display = &data->display; > struct igt_fb *small_fb = &data->small_fb; > struct igt_fb *big_fb = &data->big_fb; > int w = data->big_fb_width - small_fb->width; > @@ -337,16 +338,17 @@ static bool test_plane(data_t *data) > igt_display_commit2(&data->display, data->display.is_atomic ? > COMMIT_ATOMIC : COMMIT_UNIVERSAL); > > - > + igt_wait_for_vblank(data->drm_fd, > display->pipes[data->pipe].crtc_offset); > igt_pipe_crc_collect_crc(data->pipe_crc, &small_crc); > > igt_plane_set_fb(plane, big_fb); > igt_fb_set_position(big_fb, plane, x, y); > igt_fb_set_size(big_fb, plane, small_fb->width, > small_fb->height); > + > igt_plane_set_size(plane, data->width, data->height); > igt_display_commit2(&data->display, data->display.is_atomic ? > COMMIT_ATOMIC : COMMIT_UNIVERSAL); > - > + igt_wait_for_vblank(data->drm_fd, > display->pipes[data->pipe].crtc_offset); > igt_pipe_crc_collect_crc(data->pipe_crc, &big_crc); > > igt_plane_set_fb(plane, NULL); > -- > 2.7.4 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_dp_dsc: Avoid SIGSEGV when release DRM connector.
On Mon, May 31, 2021 at 11:34 AM Lee Shawn C wrote: > > Got SIGSEGV fault while running kms_dp_dsc test but did not > connect DP DSC capable monitor on eDP/DP port. This test daemon > should "SKIP" test without any problem. We found kms_dp_dsc > can't get proper drmModeConnector and caused this SIGSEGV fault > when release it. Make sure drmModeConnector is available before > free it can avoid this issue. > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat). Tested-by: Mark Yacoub > Signed-off-by: Lee Shawn C > --- > tests/kms_dp_dsc.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/tests/kms_dp_dsc.c b/tests/kms_dp_dsc.c > index 2446fd82bba3..ea7c9f4f72ce 100644 > --- a/tests/kms_dp_dsc.c > +++ b/tests/kms_dp_dsc.c > @@ -262,7 +262,7 @@ igt_main > data_t data = {}; > igt_output_t *output; > drmModeRes *res; > - drmModeConnector *connector; > + drmModeConnector *connector = NULL; > int i, test_conn_cnt, test_cnt; > int tests[] = {DRM_MODE_CONNECTOR_eDP, > DRM_MODE_CONNECTOR_DisplayPort}; > > @@ -311,7 +311,8 @@ igt_main > } > > igt_fixture { > - drmModeFreeConnector(connector); > + if (connector) > + drmModeFreeConnector(connector); > drmModeFreeResources(res); > close(data.debugfs_fd); > close(data.drm_fd); > -- > 2.17.1 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_dp_dsc: Transmit correct DRM connector structure.
On Mon, May 31, 2021 at 11:36 PM Lee Shawn C wrote: > > 1. Pass one more parameter (current drmModeConnector) when >call "run_test()". Use it to retrieve proper connector_type. > 2. SIGSEGV fault would happen due to "igt_output" did not >store properly in "data->output". Main funciton already >pass "igt_output" pointer into "run_test()" function. >Use this pointer instead of "data->output" to get display mode. > > Fixes: a1772be7dede ("tests/kms_dp_dsc: Bug fix for DP on Pipe A") > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat) Tested-by: Mark Yacoub > Signed-off-by: Lee Shawn C > --- > tests/kms_dp_dsc.c | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/tests/kms_dp_dsc.c b/tests/kms_dp_dsc.c > index ea7c9f4f72ce..e434384da369 100644 > --- a/tests/kms_dp_dsc.c > +++ b/tests/kms_dp_dsc.c > @@ -224,11 +224,11 @@ static void update_display(data_t *data, enum > dsc_test_type test_type) > } > > static void run_test(data_t *data, igt_output_t *output, > -enum dsc_test_type test_type) > +drmModeConnector *connector, enum dsc_test_type > test_type) > { > enum pipe pipe; > > - data->mode = igt_output_get_mode(data->output); > + data->mode = igt_output_get_mode(output); > igt_create_pattern_fb(data->drm_fd, data->mode->hdisplay, > data->mode->vdisplay, > DRM_FORMAT_XRGB, > @@ -239,7 +239,7 @@ static void run_test(data_t *data, igt_output_t *output, > if (is_i915_device(data->drm_fd)) { > uint32_t devid = intel_get_drm_devid(data->drm_fd); > > - if (data->connector->connector_type == > DRM_MODE_CONNECTOR_DisplayPort && > + if (connector->connector_type == > DRM_MODE_CONNECTOR_DisplayPort && > data->pipe == PIPE_A && IS_GEN11(devid)) { > igt_debug("DSC not supported on Pipe A on > external DP in Gen11 platforms\n"); > continue; > @@ -304,7 +304,7 @@ igt_main > continue; > } > test_conn_cnt++; > - run_test(&data, output, > test_basic_dsc_enable); > + run_test(&data, output, connector, > test_basic_dsc_enable); > } > igt_skip_on(test_conn_cnt == 0); > } > -- > 2.17.1 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] [RFC] tests/kms_flip.c: Fix subtests flip-vs-suspend
Tested it on ChromeOS and it runs well. But I think we should fix the root cause instead. On Fri, May 28, 2021 at 12:33 AM Vidya Srinivas wrote: > > Some Intel Gen11 systems are not able to do a RTC wake. > Instead change the default SUSPEND_TEST_NONE to > SUSPEND_TEST_PLATFORM. > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat) Tested-by: Mark Yacoub > Signed-off-by: Vidya Srinivas > --- > tests/kms_flip.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/tests/kms_flip.c b/tests/kms_flip.c > index 8f736652be90..8afac88c9b15 100755 > --- a/tests/kms_flip.c > +++ b/tests/kms_flip.c > @@ -835,7 +835,8 @@ static bool run_test_step(struct test_output *o, unsigned > int *events) > > if (o->flags & TEST_SUSPEND) > igt_system_suspend_autoresume(SUSPEND_STATE_MEM, > - SUSPEND_TEST_NONE); > + is_i915_device(drm_fd)? > + > SUSPEND_TEST_PLATFORM:SUSPEND_TEST_NONE); > > if (do_vblank && (o->flags & TEST_EINVAL) && o->vblank_state.count > > 0) > igt_assert(do_wait_for_vblank(o, o->pipe, target_seq, > &vbl_reply) > -- > 2.7.4 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] [RFC] tests/drm_read: Fix subtest invalid-buffer
On Fri, May 28, 2021 at 12:41 AM Vidya Srinivas wrote: > > Using (void *)-1 directly in read is aborting on chrome systems. > Following message is seen. > > Starting subtest: invalid-buffer > *** buffer overflow detected ***: terminated > Received signal SIGABRT. > Stack trace: > Aborted (core dumped) > > Patch just adds a pointer variable and uses it in read. > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat) Tested-by: Mark Yacoub > Signed-off-by: Vidya Srinivas > --- > tests/drm_read.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/tests/drm_read.c b/tests/drm_read.c > index ccf9d822fd8d..2fdec5be4078 100644 > --- a/tests/drm_read.c > +++ b/tests/drm_read.c > @@ -103,10 +103,11 @@ static void teardown(int fd) > static void test_invalid_buffer(int in) > { > int fd = setup(in, 0); > + void *add = (void *)-1; > > alarm(1); > > - igt_assert_eq(read(fd, (void *)-1, 4096), -1); > + igt_assert_eq(read(fd, add, 4096), -1); > igt_assert_eq(errno, EFAULT); > > teardown(fd); > -- > 2.7.4 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [igt-dev] [PATCH i-g-t] [RFC] tests/kms_plane_alpha_blend: Fix coverage-vs-premult-vs-constant tests
On Tue, Jun 1, 2021 at 7:54 AM Vidya Srinivas wrote: > > Few Gen11 systems show CRC mismatch. Make coverage-vs-premult-vs-constant > code similar to constant_alpha_min or basic_alpha > Tested on ChromeOS on JSL (Drawlat) Tested-by: Mark Yacoub > Signed-off-by: Vidya Srinivas > --- > tests/kms_plane_alpha_blend.c | 4 > 1 file changed, 4 deletions(-) > > diff --git a/tests/kms_plane_alpha_blend.c b/tests/kms_plane_alpha_blend.c > index a37cb27c7d62..224d79bd1749 100644 > --- a/tests/kms_plane_alpha_blend.c > +++ b/tests/kms_plane_alpha_blend.c > @@ -447,10 +447,6 @@ static void coverage_premult_constant(data_t *data, enum > pipe pipe, igt_plane_t > igt_display_t *display = &data->display; > igt_crc_t ref_crc = {}, crc = {}; > > - /* Set a background color on the primary fb for testing */ > - if (plane->type != DRM_PLANE_TYPE_PRIMARY) > - > igt_plane_set_fb(igt_pipe_get_plane_type(&display->pipes[pipe], > DRM_PLANE_TYPE_PRIMARY), &data->gray_fb); > - > igt_plane_set_prop_enum(plane, IGT_PLANE_PIXEL_BLEND_MODE, > "Coverage"); > igt_plane_set_fb(plane, &data->argb_fb_cov_7e); > igt_display_commit2(display, COMMIT_ATOMIC); > -- > 2.7.4 > > ___ > igt-dev mailing list > igt-...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/igt-dev ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH i-g-t] tests/kms_color: Remove gamma code from degamma tests
On Thu, Jun 3, 2021 at 1:04 PM Vidya Srinivas wrote: > > CRC should be collected without degamma transformation > and after drawing gradient with degamma LUT. > This patch removes things which are not related to degamma > and makes it similar to pipe gamma test. > Tested on ChromeOS on TGL (Delbin) and JSL (Drawlat) Tested-by: Mark Yacoub > Signed-off-by: Vidya Srinivas > --- > tests/kms_color.c | 16 ++-- > 1 file changed, 6 insertions(+), 10 deletions(-) > > diff --git a/tests/kms_color.c b/tests/kms_color.c > index 3a42532a5c27..2c9821cdecce 100644 > --- a/tests/kms_color.c > +++ b/tests/kms_color.c > @@ -31,8 +31,7 @@ static void test_pipe_degamma(data_t *data, > { > igt_output_t *output; > igt_display_t *display = &data->display; > - gamma_lut_t *degamma_linear, *degamma_full; > - gamma_lut_t *gamma_linear; > + gamma_lut_t *degamma_full; > color_t red_green_blue[] = { > { 1.0, 0.0, 0.0 }, > { 0.0, 1.0, 0.0 }, > @@ -42,11 +41,8 @@ static void test_pipe_degamma(data_t *data, > igt_require(igt_pipe_obj_has_prop(primary->pipe, > IGT_CRTC_DEGAMMA_LUT)); > igt_require(igt_pipe_obj_has_prop(primary->pipe, IGT_CRTC_GAMMA_LUT)); > > - degamma_linear = generate_table(data->degamma_lut_size, 1.0); > degamma_full = generate_table_max(data->degamma_lut_size); > > - gamma_linear = generate_table(data->gamma_lut_size, 1.0); > - > for_each_valid_output_on_pipe(&data->display, primary->pipe->pipe, > output) { > drmModeModeInfo *mode; > struct igt_fb fb_modeset, fb; > @@ -75,8 +71,7 @@ static void test_pipe_degamma(data_t *data, > > igt_plane_set_fb(primary, &fb_modeset); > disable_ctm(primary->pipe); > - disable_degamma(primary->pipe); > - set_gamma(data, primary->pipe, gamma_linear); > + set_degamma(data, primary->pipe, degamma_full); > igt_display_commit(&data->display); > > /* Draw solid colors with no degamma transformation. */ > @@ -92,7 +87,6 @@ static void test_pipe_degamma(data_t *data, > */ > paint_gradient_rectangles(data, mode, red_green_blue, &fb); > igt_plane_set_fb(primary, &fb); > - set_degamma(data, primary->pipe, degamma_full); > igt_display_commit(&data->display); > igt_wait_for_vblank(data->drm_fd, > > display->pipes[primary->pipe->pipe].crtc_offset); > @@ -105,13 +99,13 @@ static void test_pipe_degamma(data_t *data, > > igt_plane_set_fb(primary, NULL); > igt_output_set_pipe(output, PIPE_NONE); > + igt_display_commit2(&data->display, data->display.is_atomic ? > + COMMIT_ATOMIC : > COMMIT_LEGACY); > igt_remove_fb(data->drm_fd, &fb); > igt_remove_fb(data->drm_fd, &fb_modeset); > } > > - free_lut(degamma_linear); > free_lut(degamma_full); > - free_lut(gamma_linear); > } > > /* > @@ -191,6 +185,8 @@ static void test_pipe_gamma(data_t *data, > > igt_plane_set_fb(primary, NULL); > igt_output_set_pipe(output, PIPE_NONE); > + igt_display_commit2(&data->display, data->display.is_atomic ? > + COMMIT_ATOMIC : > COMMIT_LEGACY); > igt_remove_fb(data->drm_fd, &fb); > igt_remove_fb(data->drm_fd, &fb_modeset); > } > -- > 2.7.4 > ___ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [Intel-gfx] [PATCH] drm/i915/tgl: Set drm_crtc_state.active=false for all added disconnected CRTCs sharing MST stream.
On Tue, Oct 20, 2020 at 8:54 PM Almahallawy, Khaled wrote: > > On Wed, 2020-10-21 at 00:29 +, Souza, Jose wrote: > > On Tue, 2020-10-20 at 16:25 -0700, José Roberto de Souza wrote: > > > On Tue, 2020-10-20 at 15:41 +0300, Ville Syrjälä wrote: > > > > On Tue, Oct 20, 2020 at 12:45:55AM -0700, Khaled Almahallawy > > > > wrote: > > > > > This patch avoids failing atomic commits sent by user space by > > > > > making sure CRTC/Connector added to drm_atomic_state by the > > > > > driver are in valid state. > > > > > > > > > > When disconnecting MST hub with two or more connected displays. > > > > > The user space sends IOCTL for each MST pipe to disable. > > > > > drm_atomic_state object sent from user space contains only the > > > > > state of the crtc/pipe intended to disable. > > > > > In TGL, intel_dp_mst_atomic_master_trans_check will add all > > > > > other CRTC and connectors that share the MST stream to > > > > > drm_atomic_state: > > > > > > > > > > drm_atomic_commit > > > > >drm_atomic_helper_check_modeset > > > > >update_connector_routing > > > > >intel_dp_mst_atomic_check = funcs- > > > > > >atomic_check(connector, state); > > > > > intel_dp_mst_atomic_master_trans_check > > > > > intel_atomic_get_digital_connector_state > > > > > drm_atomic_get_connector_state <-- Add all Connectors > > > > > drm_atomic_get_crtc_state <-- Add all CRTCs > > > > >update_connector_routing <-- Check added Connector/CRTCs > > > > > - Will fail > > > > > > > > > > However the added crtc/connector pair will be in invalid state > > > > > (enabled state for a removed connector) > > > > > triggering this condition in > > > > > drm_atomic_helper.c/update_connector_routing: > > > > > > > > > > if (!state->duplicated && > > > > > drm_connector_is_unregistered(connector) && > > > > > crtc_state->active) { > > > > > DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n", > > > > > connector->base.id, connector->name); > > > > > return -EINVAL; > > > > > } > > > > > > > > Yeah, I think that "reject modeset on unregistered connectors" > > > > idea is > > > > a bit broken given how the uapi has worked in the past. Cc:ing > > > > danvet > > > > and lyude who IIRC were involved with that. > > > > > > Actually by removing this condition everything works fine as well. > However we were worried about touching this part and screwing other > stuff :-) > > > > > Hmm. Maybe we could add the other stuff to the state only after > > > > the > > > > connector .atomic_check() stuff has been done? I don't quite > > > > remember > > > > why we decided to do it here. José do you recall the details? > > > > > > Because the connector check function runs twice in > > > drm_atomic_helper_check_modeset(), in the first iteration it will > > > add all connectors that share the > > > same MST stream to state, the second one will make sure all other > > > checks passed in all connectors of the MST stream. > > > > > > To me looks like the Chrome userspace is not doing the right thing, > > > it is sending asynchronous atomic commits with conflicting state > > > between each > > > commit. > > > > Oh it do not have information about other connectors so not > > conflicting but anyways userspace should retry atomic commits > > anyways. > > > > CC: Mark and Gill for Chrome userspace input > > Yes Chrome is sending the atomic commits with correct states one after > another. Matter of fact, the failure we observe in Chrome is also > happening in Ubuntu. > > We checked that by printing the drm_atomic_state sent by user space > before atomic check: > > +++ b/drivers/gpu/drm/drm_atomic.c > @@ -1365,9 +1365,12 @@ int drm_atomic_commit(struct drm_atomic_state > *state) > struct drm_mode_config *config = &state->dev->mode_config; > int ret; > > + drm_atomic_print_state(state); > ret = drm_atomic_check_only(state); > > > Using MST with two displays and eDP connected. First MST on Pipe B and > Second MST on Pipe C. > > Chrome send atomic commit to disable Pipe B first as below: > > [ 60.406455] [drm:drm_atomic_print_state] checking c0e0cc6c > [ 60.406455] i915 :00:02.0: [drm] crtc[152]: pipe B > [ 60.406456] i915 :00:02.0: [drm] enable=0 > [ 60.406457] i915 :00:02.0: [drm] active=0 > [ 60.406458] i915 :00:02.0: [drm] self_refresh_active=0 > [ 60.406459] i915 :00:02.0: [drm] planes_changed=0 > [ 60.406460] i915 :00:02.0: [drm] mode_changed=0 > [ 60.406461] i915 :00:02.0: [drm] active_changed=0 > [ 60.406462] i915 :00:02.0: [drm] connectors_changed=0 > [ 60.406463] i915 :00:02.0: [drm] color_mgmt_changed=0 > [ 60.406464] i915 :00:02.0: [drm] plane_mask=100 > [ 60.406465] i915 :00:02.0: [drm] connector_mask=0 > [ 60.406466] i915 :00:02.0: [drm] encoder_mask=2000 > [ 60.406467] i915 :00:02.0: [drm] mode: "": 0 0 0