[PATCH 2/2] drm/i915/hdcp: Check mst_port to determine connector type
Check mst_port field in intel_connector to check connector type rather than rely on encoder as it may not be attached to connector at times. --v2 -Add closes tag [Imre] Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10898 Signed-off-by: Suraj Kandpal Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 551c862ed7a6..2edffe62f360 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -693,7 +693,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, *hdcp_capable = false; *hdcp2_capable = false; - if (!intel_encoder_is_mst(connector->encoder)) + if (!connector->mst_port) return -EINVAL; aux = >port->aux; -- 2.43.2
[PATCH 1/2] drm/i915/hdcp: Move aux assignment after connector type check
Move assignment of aux after connector type check as port may not exist if connector is not DPMST. --v2 -Fix unwanted change in intel_encoder check [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Imre Deak --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 92b03073acdd..551c862ed7a6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -687,7 +687,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, bool *hdcp2_capable) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_dp_aux *aux = >port->aux; + struct drm_dp_aux *aux; u8 bcaps; int ret; @@ -696,6 +696,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; + aux = >port->aux; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) drm_dbg_kms(>drm, -- 2.43.2
[PATCH 0/2] Fixes in hdcp remote capability
This patch series aims to avoid page fault errors caused by aux early assignment as connector may not be mst and using encoder to check for connector type. Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915/hdcp: Move aux assignment after connector type check drm/i915/hdcp: Check mst_port to determine connector type drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Check mst_port to determine connector type
Check mst_port field in intel_connector to check connector type rather than rely on encoder as it may not be attached to connector at times. --v2 -Add closes tag [Imre] Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/issues/10898 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 551c862ed7a6..2edffe62f360 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -693,7 +693,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, *hdcp_capable = false; *hdcp2_capable = false; - if (!intel_encoder_is_mst(connector->encoder)) + if (!connector->mst_port) return -EINVAL; aux = >port->aux; -- 2.43.2
[PATCH] drm/i915/pps: Disable DPLS_GATING around pps sequence
Disable bit 29 of SCLKGATE_DIS register around pps sequence when we turn panel power on. --v2 -Squash two commit together [Jani] -Use IS_DISPLAY_VER [Jani] -Fix multiline comment [Jani] --v3 -Define register in a more appropriate place [Mitul] Bspec: 49304 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_pps.c | 12 drivers/gpu/drm/i915/i915_reg.h | 4 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 0ccbf9a85914..d774aeb1673e 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -948,6 +948,14 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) intel_de_posting_read(dev_priv, pp_ctrl_reg); } + /* +* WA: 16023567976 +* Disable DPLS gating around power sequence. +*/ + if (IS_DISPLAY_VER(dev_priv, 12, 14)) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +0, DPLS_GATING_DISABLE); + pp |= PANEL_POWER_ON; if (!IS_IRONLAKE(dev_priv)) pp |= PANEL_POWER_RESET; @@ -958,6 +966,10 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) wait_panel_on(intel_dp); intel_dp->pps.last_power_on = jiffies; + if (IS_DISPLAY_VER(dev_priv, 12, 14)) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +DPLS_GATING_DISABLE, 0); + if (IS_IRONLAKE(dev_priv)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ intel_de_write(dev_priv, pp_ctrl_reg, pp); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5670eee4a498..4cc82360298b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5151,6 +5151,10 @@ enum skl_power_gate { #define _MMIO_PLANE_GAMC(plane, i, a, b) _MMIO(_PIPE(plane, a, b) + (i) * 4) +/* SCLKGATE_DIS */ +#define SCLKGATE_DIS _MMIO(0xc2020) +#define DPLS_GATING_DISABLE REG_BIT(29) + /* Plane CSC Registers */ #define _PLANE_CSC_RY_GY_1_A 0x70210 #define _PLANE_CSC_RY_GY_2_A 0x70310 -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VER >= 14. --v2 -Wa to be mentioned in comments not in commit message [Jani] -Remove blankline [Jani] --v3 -No need to write what is being done in comments when code is self explanatory [Jani] --v4 -Add comment regarding need of this WA when in TMDS mode [Chaitanya] -Write in chicken register for MTL [CHaitanya] --v5 -Fix comment [Chaitanya] -Use correct set and clear value in intel_de_rmw [Chaitanya] --v6 -No need to define C, D chicken bits it gets calculated [Animesh] Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 23 +++ drivers/gpu/drm/i915/i915_reg.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..02cbbbfd8e25 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,27 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* WA: 16022217614 */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + /* Here we assume HDMI is in TMDS mode of operation */ + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) { + if (IS_METEORLAKE(dev_priv)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder), +0, HDCP_LINE_REKEY_DISABLE); + else + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE); + } +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2026,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ae692f461982..9f2171f0adf8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3520,6 +3520,7 @@ #define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) #define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) +#define HDCP_LINE_REKEY_DISABLE REG_BIT(0) #define DISP_ARB_CTL _MMIO(0x45000) #define DISP_FBC_MEMORY_WAKE REG_BIT(31) @@ -4521,6 +4522,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH 7/7] drm/i915/dp: Write panel override luminance values
Write panel override luminance values which helps the TCON decide if tone mapping needs to be enabled or not. Signed-off-by: Suraj Kandpal Reviewed-by: Sebastian Wick --- .../drm/i915/display/intel_dp_aux_backlight.c | 25 +++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index da42f6704930..8ce60d53dcde 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -374,6 +374,29 @@ static const char *dpcd_vs_pwm_str(bool aux) return aux ? "DPCD" : "PWM"; } +static void +intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + u8 buf[4] = {}; + + buf[0] = panel->backlight.min & 0xFF; + buf[1] = (panel->backlight.min & 0xFF00) >> 8; + buf[2] = panel->backlight.max & 0xFF; + buf[3] = (panel->backlight.max & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Panel Luminance DPCD reg write failed, err:-%d\n", + ret); +} + static int intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) { @@ -405,6 +428,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + intel_dp_aux_write_panel_luminance_override(connector); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); -- 2.43.2
[PATCH 6/7] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. --v5 -Fix capability check bits. -Check colorspace before setting BT2020 --v6 -Use intel_dp_has_gamut_dip to check if we have capability to send sdp [Ville] -Seprate filling of all hdr tcon related bits into it's own function. -Check eotf data to make sure we are in HDR mode [Sebastian] --v7 -Fix confusion function name for hdr mode check [Jani] -Fix the condition which tells us if we are in HDR mode or not [Sebastian] --v8 -Call fill_hdr_tcon_param unconditionally as some parameters may not be dependent on the fact if we are in hdr mode or not [Sebastian] -Fix some conditions after change in hdr mode check [Sebastian] Signed-off-by: Suraj Kandpal Reviewed-by: Sebastian Wick --- .../drm/i915/display/intel_dp_aux_backlight.c | 98 --- 1 file changed, 87 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 1ee693df0563..da42f6704930 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -127,9 +122,6 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (ret != sizeof(tcon_cap)) return false; - if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) - return false; - drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Detected %s HDR backlight interface version %d\n", connector->base.base.id, connector->base.name, is_intel_tcon_cap(tcon_cap) ? "Intel" : "unsupported", tcon_cap[0]); @@ -137,6 +129,9 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (!is_intel_tcon_cap(tcon_cap)) return false; + if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) + return false; + /* * If we don't have HDR static metadata there is no way to * runtime detect used range for nits based control. For now @@ -225,13 +220,27 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, connector->base.base.id, connector->base.name); } +static bool +intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state) +{ + struct hdr_output_metadata *hdr_metadata; + + if (!conn_state->hdr_output_metadata) + return false; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + return hdr_metadata->hdmi_metadata_type1.eotf == HDMI_EOTF_SMPTE_ST2084; +} + static void intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel_cap.sdr_uses_aux) { + if (intel_dp_in_hdr_mode(conn_state) || + panel->backlight.edp.intel_cap.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -240,6 +249,64 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 } } +static void +intel_dp_aux_write_content_luminance(struct intel_connector *connector, +struct hdr_output_metadata *hdr_metadata) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + u8 buf[4]; + + if (!intel_dp_has_gamut_metadata_dip(connector->encoder)) + return; + + buf[0] = hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF; + buf[1] = (hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF00) >> 8; + buf[2] =
[PATCH 2/7] drm/i915/dp: Rename intel struct inside intel_panel
Rename intel to intel cap which is present inside panel.edp struct to make it more sensible to tell us what it contains. Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_display_types.h | 2 +- .../gpu/drm/i915/display/intel_dp_aux_backlight.c | 14 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 00eba3fbcdc6..66cc9c97fe58 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,7 +401,7 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; - } intel; + } intel_cap; } edp; struct backlight_device *device; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..44bc6fa04332 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -156,7 +156,7 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) return false; } - panel->backlight.edp.intel.sdr_uses_aux = + panel->backlight.edp.intel_cap.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; return true; @@ -178,7 +178,7 @@ intel_dp_aux_hdr_get_backlight(struct intel_connector *connector, enum pipe pipe } if (!(tmp & INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE)) { - if (!panel->backlight.edp.intel.sdr_uses_aux) { + if (!panel->backlight.edp.intel_cap.sdr_uses_aux) { u32 pwm_level = panel->backlight.pwm_funcs->get(connector, pipe); return intel_backlight_level_from_pwm(connector, pwm_level); @@ -221,7 +221,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel_cap.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,7 +251,7 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel_cap.sdr_uses_aux) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { @@ -275,7 +275,7 @@ intel_dp_aux_hdr_disable_backlight(const struct drm_connector_state *conn_state, struct intel_panel *panel = >panel; /* Nothing to do for AUX based backlight controls */ - if (panel->backlight.edp.intel.sdr_uses_aux) + if (panel->backlight.edp.intel_cap.sdr_uses_aux) return; /* Note we want the actual pwm_level to be 0, regardless of pwm_min */ @@ -298,9 +298,9 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", connector->base.base.id, connector->base.name, - dpcd_vs_pwm_str(panel->backlight.edp.intel.sdr_uses_aux)); + dpcd_vs_pwm_str(panel->backlight.edp.intel_cap.sdr_uses_aux)); - if (!panel->backlight.edp.intel.sdr_uses_aux) { + if (!panel->backlight.edp.intel_cap.sdr_uses_aux) { ret = panel->backlight.pwm_funcs->setup(connector, pipe); if (ret < 0) { drm_err(>drm, -- 2.43.2
[PATCH 5/7] drm/i915/dp: Drop comments on EDP HDR DPCD registers
Drop comments for EDP HDR DPCD registers as the code and conditions will tell us what can be written where. --v2 -Drop the comments altogether instead of just renaming them [Sebastian] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 85205aeb3e9a..1ee693df0563 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -69,14 +69,14 @@ #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLEBIT(0) # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) -# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ +# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLEBIT(3) # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ # define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) -#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ +#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 -- 2.43.2
[PATCH 4/7] drm/i915/dp: Fix Register bit naming
Change INTEL_EDP_HDR_TCON_SDP_COLORIMETRY enable to INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX as this bit tells TCON to ignore DPCD colorimetry values and take the one's sent through SDP. --v2 -Fix typo in commit message [Arun] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 63d99afba398..85205aeb3e9a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -74,7 +74,7 @@ # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ -# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLEBIT(7) +# define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) #define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A -- 2.43.2
[PATCH 3/7] drm/i915/dp: Add TCON HDR capability checks
Add checks to see the HDR capability of TCON panel. Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 66cc9c97fe58..da0d003102e4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,11 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; + bool supports_sdp_colorimetry; + bool supports_tone_mapping; } intel_cap; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 44bc6fa04332..63d99afba398 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -158,6 +158,16 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel_cap.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel_cap.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel_cap.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel_cap.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; + panel->backlight.edp.intel_cap.supports_sdp_colorimetry = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP; + panel->backlight.edp.intel_cap.supports_tone_mapping = + tcon_cap[1] & INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP; return true; } -- 2.43.2
[PATCH 0/7] Enable Aux Based EDP HDR
This series enables Aux based EDP HDR and backlight controls. The DPCD written to are intel proprietary and are filled based on the specs that were provided to TCON vendors. Signed-off-by: Suraj Kandpal Suraj Kandpal (7): drm/i915/dp: Make has_gamut_metadata_dip() non static drm/i915/dp: Rename intel struct inside intel_panel drm/i915/dp: Add TCON HDR capability checks drm/i915/dp: Fix Register bit naming drm/i915/dp: Drop comments on EDP HDR DPCD registers drm/i915/dp: Enable AUX based backlight for HDR drm/i915/dp: Write panel override luminance values .../drm/i915/display/intel_display_types.h| 7 +- drivers/gpu/drm/i915/display/intel_dp.c | 6 +- drivers/gpu/drm/i915/display/intel_dp.h | 1 + .../drm/i915/display/intel_dp_aux_backlight.c | 149 +++--- 4 files changed, 140 insertions(+), 23 deletions(-) -- 2.43.2
[PATCH 1/7] drm/i915/dp: Make has_gamut_metadata_dip() non static
Make has_gamut_metadata_dip() non static so it can also be used to at other places eg in intel_dp_aux_backlight. So that we can check if HW is capable of sending SDP which helps us decide if we use AUX based HDR control or via SDP. --v2 -State reason the function is needed [Arun] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 486361eb0070..6b8a94d0ca99 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6364,8 +6364,8 @@ bool intel_dp_is_port_edp(struct drm_i915_private *i915, enum port port) return _intel_dp_is_port_edp(i915, devdata, port); } -static bool -has_gamut_metadata_dip(struct intel_encoder *encoder) +bool +intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -6412,7 +6412,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) + if (intel_dp_has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) drm_connector_attach_hdr_output_metadata_property(connector); if (HAS_VRR(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 106ecfde36d9..aad2223df2a3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -196,5 +196,6 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, struct link_config_limits *limits); void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); +bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); #endif /* __INTEL_DP_H__ */ -- 2.43.2
[PATCH 0/2] Fixes in hdcp remote capability
This patch series aims to avoid page fault errors caused by aux early assignment as connector may not be mst and using encoder to check for connector type. Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915/hdcp: Move aux assignment after connector type check drm/i915/hdcp: Check mst_port to determine connector type drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Check mst_port to determine connector type
Check mst_port field in intel_connector to check connector type rather than rely on encoder as it may not be attached to connector at times. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 551c862ed7a6..2edffe62f360 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -693,7 +693,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, *hdcp_capable = false; *hdcp2_capable = false; - if (!intel_encoder_is_mst(connector->encoder)) + if (!connector->mst_port) return -EINVAL; aux = >port->aux; -- 2.43.2
[PATCH 1/2] drm/i915/hdcp: Move aux assignment after connector type check
Move assignment of aux after connector type check as port may not exist if connector is not DPMST. --v2 -Fix unwanted change in intel_encoder check [Jani] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 92b03073acdd..551c862ed7a6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -687,7 +687,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, bool *hdcp2_capable) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_dp_aux *aux = >port->aux; + struct drm_dp_aux *aux; u8 bcaps; int ret; @@ -696,6 +696,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; + aux = >port->aux; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) drm_dbg_kms(>drm, -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VER >= 14. --v2 -Wa to be mentioned in comments not in commit message [Jani] -Remove blankline [Jani] --v3 -No need to write what is being done in comments when code is self explanatory [Jani] --v4 -Add comment regarding need of this WA when in TMDS mode [Chaitanya] -Write in chicken register for MTL [CHaitanya] --v5 -Fix comment [Chaitanya] -Use correct set and clear value in intel_de_rmw [Chaitanya] Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 23 +++ drivers/gpu/drm/i915/i915_reg.h | 4 2 files changed, 27 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..02cbbbfd8e25 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,27 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* WA: 16022217614 */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + /* Here we assume HDMI is in TMDS mode of operation */ + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) { + if (IS_METEORLAKE(dev_priv)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder), +0, HDCP_LINE_REKEY_DISABLE); + else + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +0, TRANS_DDI_HDCP_LINE_REKEY_DISABLE); + } +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2026,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e22a82a5ddd7..31338d825e34 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3501,6 +3501,8 @@ [TRANSCODER_D] = _CHICKEN_TRANS_D)) #define _MTL_CHICKEN_TRANS_A 0x604e0 #define _MTL_CHICKEN_TRANS_B 0x614e0 +#define _MTL_CHICKEN_TRANS_C 0x624e0 +#define _MTL_CHICKEN_TRANS_D 0x634e0 #define MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \ _MTL_CHICKEN_TRANS_A, \ _MTL_CHICKEN_TRANS_B) @@ -3519,6 +3521,7 @@ #define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) #define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) +#define HDCP_LINE_REKEY_DISABLE REG_BIT(0) #define DISP_ARB_CTL _MMIO(0x45000) #define DISP_FBC_MEMORY_WAKE REG_BIT(31) @@ -4520,6 +4523,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Check mst_port to determine connector type
Check mst_port field in intel_connector to check connector type rather than rely on encoder as it may not be attached to connector at times. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 92be53d7c81f..2edffe62f360 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -693,7 +693,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, *hdcp_capable = false; *hdcp2_capable = false; - if (intel_encoder_is_mst(connector->encoder)) + if (!connector->mst_port) return -EINVAL; aux = >port->aux; -- 2.43.2
[PATCH 1/2] drm/i915/hdcp: Move aux assignment after connector type check
Move assignment of aux after connector type check as port may not exist if connector is not DPMST. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 92b03073acdd..92be53d7c81f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -687,15 +687,16 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, bool *hdcp2_capable) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_dp_aux *aux = >port->aux; + struct drm_dp_aux *aux; u8 bcaps; int ret; *hdcp_capable = false; *hdcp2_capable = false; - if (!intel_encoder_is_mst(connector->encoder)) + if (intel_encoder_is_mst(connector->encoder)) return -EINVAL; + aux = >port->aux; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) drm_dbg_kms(>drm, -- 2.43.2
[PATCH 0/2] Fixes in hdcp remote capability
This patch series aims to avoid page fault errors caused by aux early assignment as connector may not be mst and using encoder to check for connector type. Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915/hdcp: Move aux assignment after connector type check drm/i915/hdcp: Check mst_port to determine connector type drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) -- 2.43.2
[RFC 3/3] drm/i915: Schedule darkscreen detection work
Schedule darkscreen detection work whenever we hit FIFO underrun. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_fifo_underrun.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c index 09a7fa6c0c37..a6acd086d924 100644 --- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.c @@ -27,6 +27,7 @@ #include "i915_drv.h" #include "i915_reg.h" +#include "intel_darkscreen.h" #include "intel_de.h" #include "intel_display_irq.h" #include "intel_display_trace.h" @@ -438,6 +439,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, } intel_fbc_handle_fifo_underrun_irq(dev_priv); + intel_darkscreen_schedule_work(crtc); } /** -- 2.43.2
[RFC 2/3] drm/i915/darkscreen: Enable darkscreen detection
Add functions to enable darkscreen detection and corresponding additions to Makefile to build them. The enable and detect functions will be used in case we encounter a FIFO underrun which will help to check if a darkscreen occurred. Signed-off-by: Suraj Kandpal Signed-off-by: Nemesa Garg --- drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/display/intel_darkscreen.c | 139 ++ .../gpu/drm/i915/display/intel_darkscreen.h | 25 .../drm/i915/display/intel_display_types.h| 3 + drivers/gpu/drm/xe/Makefile | 1 + 5 files changed, 169 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_darkscreen.c create mode 100644 drivers/gpu/drm/i915/display/intel_darkscreen.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 7cad944b825c..00e36169a74d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -255,6 +255,7 @@ i915-y += \ display/intel_crtc.o \ display/intel_crtc_state_dump.o \ display/intel_cursor.o \ + display/intel_darkscreen.o \ display/intel_display.o \ display/intel_display_driver.o \ display/intel_display_irq.o \ diff --git a/drivers/gpu/drm/i915/display/intel_darkscreen.c b/drivers/gpu/drm/i915/display/intel_darkscreen.c new file mode 100644 index ..3ac3e8e6c1e3 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_darkscreen.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include "i915_reg.h" +#include "intel_de.h" +#include "intel_display_types.h" + +#define COLOR_DEPTH_6BPC 6 +#define COLOR_DEPTH_8BPC 8 +#define COLOR_DEPTH_10BPC 10 +#define COLOR_DEPTH_12BPC 12 + +#define COMPARE_VALUE_6_BPC 4 +#define COMPARE_VALUE_8_BPC 16 +#define COMPARE_VALUE_10_BPC 64 +#define COMPARE_VALUE_12_BPC 256 + +#define COMPARE_VALUE_CALCULATION_FACTOR 12 + +static void intel_darkscreen_detect(struct intel_crtc *crtc); + +static u32 intel_darkscreen_get_comp_val(struct drm_i915_private *i915, int bpc) +{ + u32 compare_value = 0; + + switch (bpc) { + case COLOR_DEPTH_6BPC: + compare_value = COMPARE_VALUE_6_BPC; + break; + case COLOR_DEPTH_8BPC: + compare_value = COMPARE_VALUE_8_BPC; + break; + case COLOR_DEPTH_10BPC: + compare_value = COMPARE_VALUE_10_BPC; + break; + case COLOR_DEPTH_12BPC: + compare_value = COMPARE_VALUE_12_BPC; + break; + default: + drm_dbg(>drm, "Bpc value is incorrect:%d\n", bpc); + return -EINVAL; + } + + compare_value = compare_value << (COMPARE_VALUE_CALCULATION_FACTOR - bpc); + return DARK_SCREEN_COMPARE_VAL(compare_value); +} + +static void intel_darkscreen_work_fn(struct work_struct *work) +{ + struct intel_darkscreen *dark_screen = + container_of(work, typeof(*dark_screen), darkscreen_detect_work); + + if (!dark_screen->enable) + intel_darkscreen_enable(dark_screen->crtc); + + intel_darkscreen_detect(dark_screen->crtc); +} + +void intel_darkscreen_schedule_work(struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_darkscreen *dark_screen = >dark_screen; + + dark_screen->crtc = crtc; + queue_work(i915->unordered_wq, _screen->darkscreen_detect_work); +} + +void intel_darkscreen_setup(struct intel_crtc *crtc) +{ + struct intel_darkscreen *dark_screen; + + dark_screen = >dark_screen; + dark_screen = kzalloc(sizeof(*dark_screen), GFP_KERNEL); + if (!dark_screen) + return; + dark_screen->enable = false; + + INIT_WORK(_screen->darkscreen_detect_work, intel_darkscreen_work_fn); +} + +/* + * Check the color format and compute the compare value based on bpc. + */ +int intel_darkscreen_enable(struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = crtc->config; + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int bpc = crtc_state->pipe_bpp / 3; + u32 val; + + if (!crtc->dark_screen.enable) + return 0; + + if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB) { + drm_dbg_kms(_priv->drm, + "YUV format not supported:%c for darkscreen detection\n", + pipe_name(crtc->pipe)); + return -EPROTO; + } + + val = intel_darkscreen_get_comp_val(dev_priv, bpc); + val |= DARK_SCREEN_ENABLE; + intel_de_write(dev_priv, DARK_SCREEN(cpu_transcoder), val); + crtc->dark_screen.enable = true; + + retu
[RFC 1/3] drm/i915: Add Dark screen detection registers
Add Dark screen detection related register and field definitions. Signed-off-by: Suraj Kandpal Signed-off-by: Nemesa Garg --- drivers/gpu/drm/i915/i915_reg.h | 8 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 8eb6c2bf4557..474b1c263517 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1838,6 +1838,14 @@ #define VRR_VSYNC_START_MASK REG_GENMASK(12, 0) #define VRR_VSYNC_START(vsync_start) REG_FIELD_PREP(VRR_VSYNC_START_MASK, (vsync_start)) +#define _DARK_SCREEN_PIPE_A0x60120 +#define DARK_SCREEN(trans) _MMIO_TRANS2(trans, _DARK_SCREEN_PIPE_A) +#define DARK_SCREEN_ENABLE REG_BIT(31) +#define DARK_SCREEN_DETECT REG_BIT(29) +#define DARK_SCREEN_DONE REG_BIT(28) +#define DARK_SCREEN_COMPARE_MASK REG_GENMASK(9, 0) +#define DARK_SCREEN_COMPARE_VAL(x) REG_FIELD_PREP(DARK_SCREEN_COMPARE_MASK, (x)) + /* VGA port control */ #define ADPA _MMIO(0x61100) #define PCH_ADPA_MMIO(0xe1100) -- 2.43.2
[RFC 0/3] Enable darkscreen detection
Fifo underrun can lead to flicker, screen corruption and blank screen in case of pipe hang. This patch series aims to enable dark screen detection whenever FIFO underruns are hit and in case we face a darkscreen at this point instead of disabling irq and fbc we want to try reset the pipe on which the underrun has occured and keep a track on the number of times underrun occurs post reset and if this persists more than 5 times we go ahead and reset the whole display. If this still persists we then fallback to disabling irq and the fb. To summarize we are using the dark screen detction feature to detect the pipe hung scenario of FIFO underrun. After detection as corrective measurements following is done. 1)pipe reset 2)display reset Comments on this design and ideas on how else this can be implemented or diffrent scenarios dark screen detection can be used are also welcome. Signed-off-by: Suraj Kandpal Suraj Kandpal (3): drm/i915: Add Dark screen detection registers drm/i915/darkscreen: Enable darkscreen detection drm/i915: Schedule darkscreen detection work drivers/gpu/drm/i915/Makefile | 1 + .../gpu/drm/i915/display/intel_darkscreen.c | 139 ++ .../gpu/drm/i915/display/intel_darkscreen.h | 25 .../drm/i915/display/intel_display_types.h| 3 + .../drm/i915/display/intel_fifo_underrun.c| 2 + drivers/gpu/drm/i915/i915_reg.h | 8 + drivers/gpu/drm/xe/Makefile | 1 + 7 files changed, 179 insertions(+) create mode 100644 drivers/gpu/drm/i915/display/intel_darkscreen.c create mode 100644 drivers/gpu/drm/i915/display/intel_darkscreen.h -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VER >= 14. --v2 -Wa to be mentioned in comments not in commit message [Jani] -Remove blankline [Jani] --v3 -No need to write what is being done in comments when code is self explanatory [Jani] --v4 -Add comment regarding need of this WA when in TMDS mode [Chaitanya] -Write in chicken register for MTL [CHaitanya] Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 26 +++ drivers/gpu/drm/i915/i915_reg.h | 4 2 files changed, 30 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..0d8ae6962d34 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,30 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* + * WA: 16022217614 + * Disable HDCP line rekeying if we are using HDMI and in + * TMDS mode. + */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) { + if (IS_METEORLAKE(dev_priv)) + intel_de_rmw(dev_priv, MTL_CHICKEN_TRANS(hdcp->cpu_transcoder), +HDCP_LINE_REKEY_DISABLE, 1); + else + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +TRANS_DDI_HDCP_LINE_REKEY_DISABLE, 1); + } +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2029,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..39b1a2d516fe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4613,6 +4613,8 @@ [TRANSCODER_D] = _CHICKEN_TRANS_D)) #define _MTL_CHICKEN_TRANS_A 0x604e0 #define _MTL_CHICKEN_TRANS_B 0x614e0 +#define _MTL_CHICKEN_TRANS_C 0x624e0 +#define _MTL_CHICKEN_TRANS_D 0x634e0 #define MTL_CHICKEN_TRANS(trans) _MMIO_TRANS((trans), \ _MTL_CHICKEN_TRANS_A, \ _MTL_CHICKEN_TRANS_B) @@ -4631,6 +4633,7 @@ #define DP_FEC_BS_JITTER_WA REG_BIT(15) #define PSR2_VSC_ENABLE_PROG_HEADER REG_BIT(12) #define DP_DSC_INSERT_SF_AT_EOL_WA REG_BIT(4) +#define HDCP_LINE_REKEY_DISABLE REG_BIT(0) #define DISP_ARB_CTL _MMIO(0x45000) #define DISP_FBC_MEMORY_WAKE REG_BIT(31) @@ -5630,6 +5633,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH 6/6] drm/i915/dp: Write panel override luminance values
Write panel override luminance values which helps the TCON decide if tone mapping needs to be enabled or not. Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 25 +++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index e23694257ea5..9e885eb40805 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -374,6 +374,29 @@ static const char *dpcd_vs_pwm_str(bool aux) return aux ? "DPCD" : "PWM"; } +static void +intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + u8 buf[4] = {}; + + buf[0] = panel->backlight.min & 0xFF; + buf[1] = (panel->backlight.min & 0xFF00) >> 8; + buf[2] = panel->backlight.max & 0xFF; + buf[3] = (panel->backlight.max & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Panel Luminance DPCD reg write failed, err:-%d\n", + ret); +} + static int intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) { @@ -405,6 +428,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + intel_dp_aux_write_panel_luminance_override(connector); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); -- 2.43.2
[PATCH 4/6] drm/i915/dp: Drop comments on EDP HDR DPCD registers
Drop comments for EDP HDR DPCD registers as the code and conditions will tell us what can be written where. --v2 -Drop the comments altogether instead of just renaming them [Sebastian] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 3d9723714c96..b61bad218994 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -69,14 +69,14 @@ #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLEBIT(0) # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) -# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ +# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLEBIT(3) # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ # define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) -#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ +#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 -- 2.43.2
[PATCH 5/6] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. --v5 -Fix capability check bits. -Check colorspace before setting BT2020 --v6 -Use intel_dp_has_gamut_dip to check if we have capability to send sdp [Ville] -Seprate filling of all hdr tcon related bits into it's own function. -Check eotf data to make sure we are in HDR mode [Sebastian] --v7 -Fix confusion function name for hdr mode check [Jani] -Fix the condition which tells us if we are in HDR mode or not [Sebastian] --v8 -Call fill_hdr_tcon_param unconditionally as some parameters may not be dependent on the fact if we are in hdr mode or not [Sebastian] -Fix some conditions after change in hdr mode check [Sebastian] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 98 --- 1 file changed, 87 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index b61bad218994..e23694257ea5 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -127,9 +122,6 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (ret != sizeof(tcon_cap)) return false; - if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) - return false; - drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Detected %s HDR backlight interface version %d\n", connector->base.base.id, connector->base.name, is_intel_tcon_cap(tcon_cap) ? "Intel" : "unsupported", tcon_cap[0]); @@ -137,6 +129,9 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (!is_intel_tcon_cap(tcon_cap)) return false; + if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) + return false; + /* * If we don't have HDR static metadata there is no way to * runtime detect used range for nits based control. For now @@ -225,13 +220,27 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, connector->base.base.id, connector->base.name); } +static bool +intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state) +{ + struct hdr_output_metadata *hdr_metadata; + + if (!conn_state->hdr_output_metadata) + return false; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + return hdr_metadata->hdmi_metadata_type1.eotf == HDMI_EOTF_SMPTE_ST2084; +} + static void intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (intel_dp_in_hdr_mode(conn_state) || + panel->backlight.edp.intel.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -240,6 +249,64 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 } } +static void +intel_dp_aux_write_content_luminance(struct intel_connector *connector, +struct hdr_output_metadata *hdr_metadata) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + u8 buf[4]; + + if (!intel_dp_has_gamut_metadata_dip(connector->encoder)) + return; + + buf[0] = hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF; + buf[1] = (hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF00) >> 8; + buf[2] = hdr_metadata->hdmi_metadata_type1.max_fal
[PATCH 1/6] drm/i915/dp: Make has_gamut_metadata_dip() non static
Make has_gamut_metadata_dip() non static so it can also be used to at other places eg in intel_dp_aux_backlight. So that we can check if HW is capable of sending SDP which helps us decide if we use AUX based HDR control or via SDP. --v2 -State reason the function is needed [Arun] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 163da48bc406..8b105efd4de9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6365,8 +6365,8 @@ bool intel_dp_is_port_edp(struct drm_i915_private *i915, enum port port) return _intel_dp_is_port_edp(i915, devdata, port); } -static bool -has_gamut_metadata_dip(struct intel_encoder *encoder) +bool +intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -6413,7 +6413,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) + if (intel_dp_has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) drm_connector_attach_hdr_output_metadata_property(connector); if (HAS_VRR(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 106ecfde36d9..aad2223df2a3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -196,5 +196,6 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, struct link_config_limits *limits); void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); +bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); #endif /* __INTEL_DP_H__ */ -- 2.43.2
[PATCH 2/6] drm/i915/dp: Add TCON HDR capability checks
Add checks to see the HDR capability of TCON panel. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 62f7a30c37dc..1cf4caf1a0a9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,11 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; + bool supports_sdp_colorimetry; + bool supports_tone_mapping; } intel; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..94edf982eff8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -158,6 +158,16 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; + panel->backlight.edp.intel.supports_sdp_colorimetry = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP; + panel->backlight.edp.intel.supports_tone_mapping = + tcon_cap[1] & INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP; return true; } -- 2.43.2
[PATCH 3/6] drm/i915/dp: Fix Register bit naming
Change INTEL_EDP_HDR_TCON_SDP_COLORIMETRY enable to INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX as this bit is tells TCON to ignore DPCD colorimetry values and take the one's sent through SDP. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 94edf982eff8..3d9723714c96 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -74,7 +74,7 @@ # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ -# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLEBIT(7) +# define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) #define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A -- 2.43.2
[PATCH 0/6] Enable Aux Based EDP HDR
This series enables Aux based EDP HDR and backlight controls. The DPCD written to are intel proprietary and are filled based on the specs that were provided to TCON vendors. Signed-off-by: Suraj Kandpal Suraj Kandpal (6): drm/i915/dp: Make has_gamut_metadata_dip() non static drm/i915/dp: Add TCON HDR capability checks drm/i915/dp: Fix Register bit naming drm/i915/dp: Drop comments on EDP HDR DPCD registers drm/i915/dp: Enable AUX based backlight for HDR drm/i915/dp: Write panel override luminance values .../drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp.c | 6 +- drivers/gpu/drm/i915/display/intel_dp.h | 1 + .../drm/i915/display/intel_dp_aux_backlight.c | 139 -- 4 files changed, 134 insertions(+), 17 deletions(-) -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VER >= 14. --v2 -Wa to be mentioned in comments not in commit message [Jani] -Remove blankline [Jani] --v3 -No need to write what is being done in comments when code is self explanatory [Jani] Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 17 + drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..78b20f23a2e1 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,21 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* WA: 16022217614 */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +TRANS_DDI_HDCP_LINE_REKEY_DISABLE, 1); +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2020,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..fbf4623cd536 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5630,6 +5630,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH] drm/i915/pps: Disable DPLS_GATING around pps sequence
Disable bit 29 of SCLKGATE_DIS register around pps sequence when we turn panel power on. --v2 -Squash two commit together [Jani] -Use IS_DISPLAY_VER [Jani] -Fix multiline comment [Jani] Bspec: 49304 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_pps.c | 12 drivers/gpu/drm/i915/i915_reg.h | 4 2 files changed, 16 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 3078dfac7817..2b2cead22a7d 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -948,6 +948,14 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) intel_de_posting_read(dev_priv, pp_ctrl_reg); } + /* +* WA: 16023567976 +* Disable DPLS gating around power sequence. +*/ + if (IS_DISPLAY_VER(dev_priv, 12, 14)) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +DPLS_GATING_DISABLE, 1); + pp |= PANEL_POWER_ON; if (!IS_IRONLAKE(dev_priv)) pp |= PANEL_POWER_RESET; @@ -958,6 +966,10 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) wait_panel_on(intel_dp); intel_dp->pps.last_power_on = jiffies; + if (IS_DISPLAY_VER(dev_priv, 12, 14)) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +DPLS_GATING_DISABLE, 0); + if (IS_IRONLAKE(dev_priv)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ intel_de_write(dev_priv, pp_ctrl_reg, pp); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..1c2cd6cc254f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6250,6 +6250,10 @@ enum skl_power_gate { #define SFUSE_STRAP_DDIC_DETECTED (1 << 1) #define SFUSE_STRAP_DDID_DETECTED (1 << 0) +/* SCLKGATE_DIS */ +#define SCLKGATE_DIS _MMIO(0xc2020) +#define DPLS_GATING_DISABLE REG_BIT(29) + #define WM_MISC_MMIO(0x45260) #define WM_MISC_DATA_PARTITION_5_6(1 << 0) -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VER >= 14. --v2 -Wa to be mentioned in comments not in commit message [Jani] -Remove blankline [Jani] Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 22 ++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..4b1833742245 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,26 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +/* + * WA: 16022217614 + * Disable HDCP Line Rekeying when HDCP ver > 1.4 + * and when we are on HDMI TMDS operation + * for DISPLAY_VEY >= 14. + */ +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +TRANS_DDI_HDCP_LINE_REKEY_DISABLE, 1); +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2025,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..fbf4623cd536 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5630,6 +5630,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH 0/2] Disable DPLS Gating around PPS
Disable DPLS Gating around Panel Power on Sequence. WA:16023567976 Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915: Add SCLKGATE_DIS register definition drm/i915/pps: Disable DPLS_GATING around pps sequence drivers/gpu/drm/i915/display/intel_pps.c | 12 drivers/gpu/drm/i915/i915_reg.h | 4 2 files changed, 16 insertions(+) -- 2.43.2
[PATCH 2/2] drm/i915/pps: Disable DPLS_GATING around pps sequence
Disable bit 29 of SCLKGATE_DIS register around pps sequence when we turn panel power on. WA: 16023567976 Bspec: 49304 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_pps.c | 12 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 3078dfac7817..a912e712ca63 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -919,6 +919,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u32 pp; i915_reg_t pp_ctrl_reg; + int dis_ver = DISPLAY_VER(dev_priv); lockdep_assert_held(_priv->display.pps.mutex); @@ -948,6 +949,13 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) intel_de_posting_read(dev_priv, pp_ctrl_reg); } + /* WA: 16023567976 +* Disable DPLS gating around power sequence. +*/ + if (dis_ver >= 12 && dis_ver <= 14) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +DPLS_GATING_DISABLE, 1); + pp |= PANEL_POWER_ON; if (!IS_IRONLAKE(dev_priv)) pp |= PANEL_POWER_RESET; @@ -958,6 +966,10 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp) wait_panel_on(intel_dp); intel_dp->pps.last_power_on = jiffies; + if (dis_ver >= 12 && dis_ver <= 14) + intel_de_rmw(dev_priv, SCLKGATE_DIS, +DPLS_GATING_DISABLE, 0); + if (IS_IRONLAKE(dev_priv)) { pp |= PANEL_POWER_RESET; /* restore panel reset bit */ intel_de_write(dev_priv, pp_ctrl_reg, pp); -- 2.43.2
[PATCH 1/2] drm/i915: Add SCLKGATE_DIS register definition
Add SCLKGATE_DIS register and it's register definition which will be used the next patch. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/i915_reg.h | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..beec91a2f493 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6250,6 +6250,10 @@ enum skl_power_gate { #define SFUSE_STRAP_DDIC_DETECTED (1 << 1) #define SFUSE_STRAP_DDID_DETECTED (1 << 0) +/* SCLKGATE_DIS */ +#define SCLKGATE_DIS _MMIO(0xc2014) +#define DPLS_GATING_DISABLE REG_BIT(29) + #define WM_MISC_MMIO(0x45260) #define WM_MISC_DATA_PARTITION_5_6(1 << 0) -- 2.43.2
[PATCH] drm/i915/hdcp: Disable HDCP Line Rekeying for HDCP2.2 on HDMI
Disable HDCP Line Rekeying when HDCP ver > 1.4 and when we are on HDMI TMDS operation for DISPLAY_VEY >= 14. WA: 16022217614 Bspec: 49273 Bspec: 69964 Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 16 drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index d5ed4c7dfbc0..15af6e184ef8 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,6 +30,20 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 +static void +intel_hdcp_disable_hdcp_line_rekeying(struct intel_encoder *encoder, + struct intel_hdcp *hdcp) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (encoder->type != INTEL_OUTPUT_HDMI) + return; + + if (DISPLAY_VER(dev_priv) >= 14) + intel_de_rmw(dev_priv, TRANS_DDI_FUNC_CTL(hdcp->cpu_transcoder), +TRANS_DDI_HDCP_LINE_REKEY_DISABLE, 1); +} + static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { @@ -2005,6 +2019,8 @@ static int _intel_hdcp2_enable(struct intel_atomic_state *state, connector->base.base.id, connector->base.name, hdcp->content_type); + intel_hdcp_disable_hdcp_line_rekeying(connector->encoder, hdcp); + ret = hdcp2_authenticate_and_encrypt(state, connector); if (ret) { drm_dbg_kms(>drm, "HDCP2 Type%d Enabling Failed. (%d)\n", diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f34efcd7d6c..fbf4623cd536 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5630,6 +5630,7 @@ enum skl_power_gate { #define TRANS_DDI_EDP_INPUT_B_ONOFF (5 << 12) #define TRANS_DDI_EDP_INPUT_C_ONOFF (6 << 12) #define TRANS_DDI_EDP_INPUT_D_ONOFF (7 << 12) +#define TRANS_DDI_HDCP_LINE_REKEY_DISABLE REG_BIT(12) #define TRANS_DDI_MST_TRANSPORT_SELECT_MASK REG_GENMASK(11, 10) #define TRANS_DDI_MST_TRANSPORT_SELECT(trans) \ REG_FIELD_PREP(TRANS_DDI_MST_TRANSPORT_SELECT_MASK, trans) -- 2.43.2
[PATCH 6/6] drm/i915/dp: Write panel override luminance values
Write panel override luminance values which helps the TCON decide if tone mapping needs to be enabled or not. Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 25 +++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index b13eee250dc4..cb6f01daae42 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -381,6 +381,29 @@ static const char *dpcd_vs_pwm_str(bool aux) return aux ? "DPCD" : "PWM"; } +static void +intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + u8 buf[4] = {}; + + buf[0] = panel->backlight.min & 0xFF; + buf[1] = (panel->backlight.min & 0xFF00) >> 8; + buf[2] = panel->backlight.max & 0xFF; + buf[3] = (panel->backlight.max & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Panel Luminance DPCD reg write failed, err:-%d\n", + ret); +} + static int intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) { @@ -412,6 +435,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + intel_dp_aux_write_panel_luminance_override(connector); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); -- 2.43.2
[PATCH 5/6] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. --v5 -Fix capability check bits. -Check colorspace before setting BT2020 --v6 -Use intel_dp_has_gamut_dip to check if we have capability to send sdp [Ville] -Seprate filling of all hdr tcon related bits into it's own function. -Check eotf data to make sure we are in HDR mode [Sebastian] --v7 -Fix confusion function name for hdr mode check [Jani] -Fix the condition which tells us if we are in HDR mode or not [Sebastian] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 105 -- 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index b61bad218994..b13eee250dc4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -127,9 +122,6 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (ret != sizeof(tcon_cap)) return false; - if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) - return false; - drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Detected %s HDR backlight interface version %d\n", connector->base.base.id, connector->base.name, is_intel_tcon_cap(tcon_cap) ? "Intel" : "unsupported", tcon_cap[0]); @@ -137,6 +129,9 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (!is_intel_tcon_cap(tcon_cap)) return false; + if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) + return false; + /* * If we don't have HDR static metadata there is no way to * runtime detect used range for nits based control. For now @@ -225,13 +220,27 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, connector->base.base.id, connector->base.name); } +static bool +intel_dp_in_hdr_mode(const struct drm_connector_state *conn_state) +{ + struct hdr_output_metadata *hdr_metadata; + + if (!conn_state->hdr_output_metadata) + return false; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + return hdr_metadata->hdmi_metadata_type1.eotf == HDMI_EOTF_SMPTE_ST2084; +} + static void intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (intel_dp_in_hdr_mode(conn_state) || + panel->backlight.edp.intel.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -240,6 +249,70 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 } } +static void +intel_dp_aux_write_content_luminance(struct intel_connector *connector, +struct hdr_output_metadata *hdr_metadata) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + u8 buf[4]; + + if (!intel_dp_has_gamut_metadata_dip(connector->encoder)) + return; + + buf[0] = hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF; + buf[1] = (hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF00) >> 8; + buf[2] = hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF; + buf[3] = (hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_CONTENT_LUMI
[PATCH 3/6] drm/i915/dp: Fix Register bit naming
Change INTEL_EDP_HDR_TCON_SDP_COLORIMETRY enable to INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX as this bit is tells TCON to ignore DPCD colorimetry values and take the one's sent through SDP. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 94edf982eff8..3d9723714c96 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -74,7 +74,7 @@ # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ -# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLEBIT(7) +# define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) #define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A -- 2.43.2
[PATCH 4/6] drm/i915/dp: Drop comments on EDP HDR DPCD registers
Drop comments for EDP HDR DPCD registers as the code and conditions will tell us what can be written where. --v2 -Drop the comments altogether instead of just renaming them [Sebastian] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 3d9723714c96..b61bad218994 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -69,14 +69,14 @@ #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLEBIT(0) # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) -# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ +# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLEBIT(3) # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ # define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) -#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ +#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 -- 2.43.2
[PATCH 1/6] drm/i915/dp: Make has_gamut_metadata_dip() non static
Make has_gamut_metadata_dip() non static so it can also be used to at other places eg in intel_dp_aux_backlight. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 163da48bc406..8b105efd4de9 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6365,8 +6365,8 @@ bool intel_dp_is_port_edp(struct drm_i915_private *i915, enum port port) return _intel_dp_is_port_edp(i915, devdata, port); } -static bool -has_gamut_metadata_dip(struct intel_encoder *encoder) +bool +intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -6413,7 +6413,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) + if (intel_dp_has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) drm_connector_attach_hdr_output_metadata_property(connector); if (HAS_VRR(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index 106ecfde36d9..aad2223df2a3 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -196,5 +196,6 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, struct link_config_limits *limits); void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); +bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); #endif /* __INTEL_DP_H__ */ -- 2.43.2
[PATCH 2/6] drm/i915/dp: Add TCON HDR capability checks
Add checks to see the HDR capability of TCON panel. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 0f4bd5710796..ef28eee05ec6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,11 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; + bool supports_sdp_colorimetry; + bool supports_tone_mapping; } intel; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..94edf982eff8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -158,6 +158,16 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; + panel->backlight.edp.intel.supports_sdp_colorimetry = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP; + panel->backlight.edp.intel.supports_tone_mapping = + tcon_cap[1] & INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP; return true; } -- 2.43.2
[PATCH 0/6] Enable Aux Based EDP HDR
This series enables Aux based EDP HDR and backlight controls. The DPCD written to are intel proprietary and are filled based on the specs that were provided to TCON vendors. Signed-off-by: Suraj Kandpal Suraj Kandpal (6): drm/i915/dp: Make has_gamut_metadata_dip() non static drm/i915/dp: Add TCON HDR capability checks drm/i915/dp: Fix Register bit naming drm/i915/dp: Drop comments on EDP HDR DPCD registers drm/i915/dp: Enable AUX based backlight for HDR drm/i915/dp: Write panel override luminance values .../drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp.c | 6 +- drivers/gpu/drm/i915/display/intel_dp.h | 1 + .../drm/i915/display/intel_dp_aux_backlight.c | 146 -- 4 files changed, 141 insertions(+), 17 deletions(-) -- 2.43.2
[PATCH 7/7] drm/i915/dp: Limit brightness level to vbt min brightness
Limit minimum brightness to vbt min brightness when using aux based brightness control to avoid letting the screen from going completely blank. Sometimes vbt can have some bogus values hence clamping the value for sanity in case of corner case. --v2 -Use something same mechanism to limit minimum brightness that PWM method uses [Jani] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 20dd5a6a0f3f..eb2a7225dfaa 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -411,6 +411,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi struct intel_panel *panel = >panel; struct drm_luminance_range_info *luminance_range = >base.display_info.luminance_range; + u32 min_level = clamp_t(u32, + connector->panel.vbt.backlight.min_brightness, 0, 64); int ret; drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", @@ -427,14 +429,12 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi } } - if (luminance_range->max_luminance) { + if (luminance_range->max_luminance) panel->backlight.max = luminance_range->max_luminance; - panel->backlight.min = luminance_range->min_luminance; - } else { + else panel->backlight.max = 512; - panel->backlight.min = 0; - } + panel->backlight.min = min_level; intel_dp_aux_write_panel_luminance_override(connector); drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", -- 2.43.2
[PATCH 7/7] drm/i915/dp: Limit brightness level to 20
Limit minimum brightness to 20 when using aux based brightness control to avoid letting the screen going completely blank. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 20dd5a6a0f3f..b54ea7e46954 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -211,6 +211,9 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 buf[4] = {}; + if (level < 20) + level = 20; + buf[0] = level & 0xFF; buf[1] = (level & 0xFF00) >> 8; -- 2.43.2
[PATCH 6/7] drm/i915/dp: Write panel override luminance values
Write panel override luminance values which helps the TCON decide if tone mapping needs to be enabled or not. Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 25 +++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 7af876e2d210..20dd5a6a0f3f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -381,6 +381,29 @@ static const char *dpcd_vs_pwm_str(bool aux) return aux ? "DPCD" : "PWM"; } +static void +intel_dp_aux_write_panel_luminance_override(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + int ret; + u8 buf[4] = {}; + + buf[0] = panel->backlight.min & 0xFF; + buf[1] = (panel->backlight.min & 0xFF00) >> 8; + buf[2] = panel->backlight.max & 0xFF; + buf[3] = (panel->backlight.max & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE, + buf, sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Panel Luminance DPCD reg write failed, err:-%d\n", + ret); +} + static int intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pipe) { @@ -412,6 +435,8 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + intel_dp_aux_write_panel_luminance_override(connector); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); -- 2.43.2
[PATCH 5/7] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. --v5 -Fix capability check bits. -Check colorspace before setting BT2020 --v6 -Use intel_dp_has_gamut_dip to check if we have capability to send sdp [Ville] -Seprate filling of all hdr tcon related bits into it's own function. -Check eotf data to make sure we are in HDR mode [Sebastian] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 105 -- 1 file changed, 94 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 2d50a4734823..7af876e2d210 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -127,9 +122,6 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (ret != sizeof(tcon_cap)) return false; - if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) - return false; - drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Detected %s HDR backlight interface version %d\n", connector->base.base.id, connector->base.name, is_intel_tcon_cap(tcon_cap) ? "Intel" : "unsupported", tcon_cap[0]); @@ -137,6 +129,9 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) if (!is_intel_tcon_cap(tcon_cap)) return false; + if (!(tcon_cap[1] & INTEL_EDP_HDR_TCON_BRIGHTNESS_NITS_CAP)) + return false; + /* * If we don't have HDR static metadata there is no way to * runtime detect used range for nits based control. For now @@ -225,13 +220,27 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, connector->base.base.id, connector->base.name); } +static bool +intel_dp_aux_in_hdr_mode(const struct drm_connector_state *conn_state) +{ + struct hdr_output_metadata *hdr_metadata; + + if (!conn_state->hdr_output_metadata) + return false; + + hdr_metadata = conn_state->hdr_output_metadata->data; + + return hdr_metadata->hdmi_metadata_type1.eotf != HDMI_EOTF_TRADITIONAL_GAMMA_SDR; +} + static void intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 level) { struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (intel_dp_aux_in_hdr_mode(conn_state) || + panel->backlight.edp.intel.sdr_uses_aux) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -240,6 +249,70 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 } } +static void +intel_dp_aux_write_content_luminance(struct intel_connector *connector, +struct hdr_output_metadata *hdr_metadata) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + struct drm_i915_private *i915 = to_i915(connector->base.dev); + int ret; + u8 buf[4]; + + if (!intel_dp_has_gamut_metadata_dip(connector->encoder)) + return; + + buf[0] = hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF; + buf[1] = (hdr_metadata->hdmi_metadata_type1.max_cll & 0xFF00) >> 8; + buf[2] = hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF; + buf[3] = (hdr_metadata->hdmi_metadata_type1.max_fall & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, + INTEL_EDP_HDR_CONTENT_LUMINANCE, + buf, sizeof(buf)); + if (ret < 0) +
[PATCH 4/7] drm/i915/dp: Fix comments on EDP HDR DPCD registers
Change comments from Pre-TGL+ to Pre-ICL as mentioned in specs Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 3d9723714c96..2d50a4734823 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -69,14 +69,14 @@ #define INTEL_EDP_HDR_GETSET_CTRL_PARAMS 0x344 # define INTEL_EDP_HDR_TCON_2084_DECODE_ENABLEBIT(0) # define INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE BIT(1) -# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-TGL+ */ +# define INTEL_EDP_HDR_TCON_TONE_MAPPING_ENABLE BIT(2) /* Pre-ICL */ # define INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLEBIT(3) # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ # define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) -#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ +#define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-ICL */ #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A #define INTEL_EDP_SDR_LUMINANCE_LEVEL 0x352 #define INTEL_EDP_BRIGHTNESS_NITS_LSB 0x354 -- 2.43.2
[PATCH 3/7] drm/i915/dp: Fix Register bit naming
Change INTEL_EDP_HDR_TCON_SDP_COLORIMETRY enable to INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX as this bit is tells TCON to ignore DPCD colorimetry values and take the one's sent through SDP. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 94edf982eff8..3d9723714c96 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -74,7 +74,7 @@ # define INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE BIT(4) # define INTEL_EDP_HDR_TCON_SRGB_TO_PANEL_GAMUT_ENABLEBIT(5) /* Bit 6 is reserved */ -# define INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_ENABLEBIT(7) +# define INTEL_EDP_HDR_TCON_SDP_OVERRIDE_AUX BIT(7) #define INTEL_EDP_HDR_CONTENT_LUMINANCE0x346 /* Pre-TGL+ */ #define INTEL_EDP_HDR_PANEL_LUMINANCE_OVERRIDE 0x34A -- 2.43.2
[PATCH 2/7] drm/i915/dp: Add TCON HDR capability checks
Add checks to see the HDR capability of TCON panel. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 10 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 4ef1f5f709d8..ebee6ebf1fdb 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,11 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; + bool supports_sdp_colorimetry; + bool supports_tone_mapping; } intel; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..94edf982eff8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -158,6 +158,16 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; + panel->backlight.edp.intel.supports_sdp_colorimetry = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SDP_COLORIMETRY_CAP; + panel->backlight.edp.intel.supports_tone_mapping = + tcon_cap[1] & INTEL_EDP_HDR_TCON_TONE_MAPPING_CAP; return true; } -- 2.43.2
[PATCH 1/7] drm/i915/dp: Make has_gamut_metadata_dip() non static
Make has_gamut_metadata_dip() non static so it can also be used to at other places eg in intel_dp_aux_backlight. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dp.h | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a11bc4fd3d65..26ccd4cc0d48 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -6226,8 +6226,8 @@ bool intel_dp_is_port_edp(struct drm_i915_private *i915, enum port port) return _intel_dp_is_port_edp(i915, devdata, port); } -static bool -has_gamut_metadata_dip(struct intel_encoder *encoder) +bool +intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); enum port port = encoder->port; @@ -6274,7 +6274,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) + if (intel_dp_has_gamut_metadata_dip(_to_dig_port(intel_dp)->base)) drm_connector_attach_hdr_output_metadata_property(connector); if (HAS_VRR(dev_priv)) diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index c540d3a73fe7..bbd61cbedc4f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -193,5 +193,6 @@ intel_dp_compute_config_link_bpp_limits(struct intel_dp *intel_dp, struct link_config_limits *limits); void intel_dp_get_dsc_sink_cap(u8 dpcd_rev, struct intel_connector *connector); +bool intel_dp_has_gamut_metadata_dip(struct intel_encoder *encoder); #endif /* __INTEL_DP_H__ */ -- 2.43.2
[PATCH 0/7] Enable Aux Based EDP HDR
This series enables Aux based EDP HDR and backlight controls. The DPCD written to are intel proprietary and are filled based on the specs that were provided to TCON vendors. Signed-off-by: Suraj Kandpal Suraj Kandpal (7): drm/i915/dp: Make has_gamut_metadata_dip() non static drm/i915/dp: Add TCON HDR capability checks drm/i915/dp: Fix Register bit naming drm/i915/dp: Fix comments on EDP HDR DPCD registers drm/i915/dp: Enable AUX based backlight for HDR drm/i915/dp: Write panel override luminance values drm/i915/dp: Limit brightness level to 20 .../drm/i915/display/intel_display_types.h| 5 + drivers/gpu/drm/i915/display/intel_dp.c | 6 +- drivers/gpu/drm/i915/display/intel_dp.h | 1 + .../drm/i915/display/intel_dp_aux_backlight.c | 149 -- 4 files changed, 144 insertions(+), 17 deletions(-) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Fix get remote hdcp capability function
HDCP 1.x capability needs to be checked even if setup is not HDCP 2.x capable. --v2 -Assign hdcp_capable and hdcp2_capable to false [Chaitanya] --v3 -Fix variable assignment [Chaitanya] Fixes: 813cca96e4ac ("drm/i915/hdcp: Add new remote capability check shim function") Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 179e754e5c30..92b03073acdd 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -691,12 +691,15 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, u8 bcaps; int ret; + *hdcp_capable = false; + *hdcp2_capable = false; if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) - return ret; + drm_dbg_kms(>drm, + "HDCP2 DPCD capability read failed err: %d\n", ret); ret = intel_dp_hdcp_read_bcaps(aux, i915, ); if (ret) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Fix get remote hdcp capability function
HDCP 1.x capability needs to be checked even if setup is not HDCP 2.x capable. --v2 -Assign hdcp_capable and hdcp2_capable to false [Chaitanya] Fixes: 813cca96e4ac ("drm/i915/hdcp: Add new remote capability check shim function") Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 179e754e5c30..bd2cd7417136 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -694,9 +694,12 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; + hdcp_capable = false; + hdcp2_capable = false; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) - return ret; + drm_dbg_kms(>drm, + "HDCP2 DPCD capability read failed err: %d\n", ret); ret = intel_dp_hdcp_read_bcaps(aux, i915, ); if (ret) -- 2.43.2
[PATCH 1/2] drm/i915/display: Initialize capability variables
Initialize HDCP capability variables to false to avoid UBSAN warning in boolean value as some functions invoking this could return without filling the two capability values. --v2 -Fix Typo [Chaitanya] Signed-off-by: Suraj Kandpal Reviewed-by: Chaitanya Kumar Borah --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b99c024b0934..95d14dab089e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -191,7 +191,7 @@ static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, bool remote_req) { - bool hdcp_cap, hdcp2_cap; + bool hdcp_cap = false, hdcp2_cap = false; if (!intel_connector->hdcp.shim) { seq_puts(m, "No Connector Support"); -- 2.43.2
[PATCH 0/2] Fix UBSAN warning in hdcp_info
This patch series fixes the UBSAN warning which gets called when hdcp_info is invoked accompanied by some other logical fixes required in the hdcp capability function. Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915/display: Initialize capability variables drm/i915/hdcp: Fix get remote hdcp capability function drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 - 2 files changed, 5 insertions(+), 2 deletions(-) -- 2.43.2
[PATCH 2/2] drm/i915/hdcp: Fix get remote hdcp capability function
HDCP 1.x capability needs to be checked even if setup is not HDCP 2.x capable. Fixes: 813cca96e4ac ("drm/i915/hdcp: Add new remote capability check shim function") Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index b98a87883fef..7f52043b0f9f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -688,7 +688,7 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct drm_dp_aux *aux = >port->aux; - u8 bcaps; + u8 bcaps = 0; int ret; if (!intel_encoder_is_mst(connector->encoder)) @@ -696,15 +696,14 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) - return ret; + drm_dbg_kms(>drm, + "HDCP2 DPCD capability read failed err: %d\n", ret); ret = intel_dp_hdcp_read_bcaps(aux, i915, ); - if (ret) - return ret; *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE; - return 0; + return ret; } static const struct intel_hdcp_shim intel_dp_hdcp_shim = { -- 2.43.2
[PATCH 1/2] drm/i915/display: Initialize capability variables
Initialize HDCP capability variables to false to avoid UBSAN warning in boolean value. --v2 -Fix Typo [Chaitanya] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b99c024b0934..95d14dab089e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -191,7 +191,7 @@ static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, bool remote_req) { - bool hdcp_cap, hdcp2_cap; + bool hdcp_cap = false, hdcp2_cap = false; if (!intel_connector->hdcp.shim) { seq_puts(m, "No Connector Support"); -- 2.43.2
[PATCH 0/2] Fix UBSAN warning in hdcp_info
This patch series fixes the UBSAN warning which gets called when hdcp_info is invoked accompanied by some other logical fixes required in the hdcp capability function. Signed-off-by: Suraj Kandpal Suraj Kandpal (2): drm/i915/display: Initialize capability variables drm/i915/hdcp: Fix get remote hdcp capability function drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 9 - 2 files changed, 5 insertions(+), 6 deletions(-) -- 2.43.2
[PATCH] drm/i915/display: Initalizalize capability variables
Initialize HDCP capability variables to false to avoid UBSAN warning in boolean value. Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b99c024b0934..95d14dab089e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -191,7 +191,7 @@ static void intel_hdcp_info(struct seq_file *m, struct intel_connector *intel_connector, bool remote_req) { - bool hdcp_cap, hdcp2_cap; + bool hdcp_cap = false, hdcp2_cap = false; if (!intel_connector->hdcp.shim) { seq_puts(m, "No Connector Support"); -- 2.43.2
[PATCH] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. --v5 -Fix capability check bits. -Check colorspace before setting BT2020 Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_display_types.h| 3 + .../drm/i915/display/intel_dp_aux_backlight.c | 57 --- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e67cd5b02e84..271bb609106d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,9 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; } intel; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..f927e259b540 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -158,6 +153,12 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel.supports_2084_decode = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel.supports_2020_gamut = + tcon_cap[1] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel.supports_segmented_backlight = + tcon_cap[1] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; return true; } @@ -206,6 +207,9 @@ intel_dp_aux_hdr_set_aux_backlight(const struct drm_connector_state *conn_state, struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); u8 buf[4] = {}; + if (level < 20) + level = 20; + buf[0] = level & 0xFF; buf[1] = (level & 0xFF00) >> 8; @@ -221,7 +225,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,8 +255,30 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + + if (conn_state->hdr_output_metadata) { + struct hdr_output_metadata *hdr_metadata = + conn_state->hdr_output_metadata->data; + + if (panel->backlight.edp.intel.supports_segmented_backlight && + hdr_metadata->hdmi_metadata_type1.eotf >= + HDMI_EOTF_TRADITIONAL_GAMMA_HDR) + ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + if (panel->backlight.edp.intel.supports_2084_decode && + hdr_metadata->hdmi_metadata_type1.eotf == + HDMI_EOTF_SMPTE_ST2084) + ctrl |= INTEL_EDP_HDR_TCON_2084_D
[PATCH] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] --v4 -Add checks for HDR TCON cap bits [Ville] -Check eotf of hdr_output_data and sets bits base of that value. Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_display_types.h| 3 ++ .../drm/i915/display/intel_dp_aux_backlight.c | 51 --- 2 files changed, 46 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e67cd5b02e84..271bb609106d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -401,6 +401,9 @@ struct intel_panel { } vesa; struct { bool sdr_uses_aux; + bool supports_2084_decode; + bool supports_2020_gamut; + bool supports_segmented_backlight; } intel; } edp; diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..74270c4755e7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -158,6 +153,12 @@ intel_dp_aux_supports_hdr_backlight(struct intel_connector *connector) panel->backlight.edp.intel.sdr_uses_aux = tcon_cap[2] & INTEL_EDP_SDR_TCON_BRIGHTNESS_AUX_CAP; + panel->backlight.edp.intel.supports_2084_decode = + tcon_cap[2] & INTEL_EDP_HDR_TCON_2084_DECODE_CAP; + panel->backlight.edp.intel.supports_2020_gamut = + tcon_cap[2] & INTEL_EDP_HDR_TCON_2020_GAMUT_CAP; + panel->backlight.edp.intel.supports_segmented_backlight = + tcon_cap[2] & INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_CAP; return true; } @@ -221,7 +222,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,8 +252,27 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + + if (conn_state->hdr_output_metadata) { + struct hdr_output_metadata *hdr_metadata = + conn_state->hdr_output_metadata->data; + + if (panel->backlight.edp.intel.supports_segmented_backlight && + hdr_metadata->hdmi_metadata_type1.eotf >= + HDMI_EOTF_TRADITIONAL_GAMMA_HDR) + ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + if (panel->backlight.edp.intel.supports_2084_decode && + hdr_metadata->hdmi_metadata_type1.eotf == + HDMI_EOTF_SMPTE_ST2084) + ctrl |= INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE; + if (panel->backlight.edp.intel.supports_2020_gamut && + hdr_metadata->hdmi_metadata_type1.eotf >= + HDMI_EOTF_TRADITIONAL_GAMMA_HDR) + ctrl |= INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE; + } + intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else {
[PATCH] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] --v3 -Content Luminance needs to be sent only for pre-ICL after that it is directly picked up from hdr metadata [Ville] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 33 ++- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..cba7b8f5dad4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -221,7 +216,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,8 +246,15 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + + if (conn_state->hdr_output_metadata) { + ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE; + } + intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -292,9 +294,11 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); struct drm_luminance_range_info *luminance_range = >base.display_info.luminance_range; int ret; + u8 buf[4]; drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", connector->base.base.id, connector->base.name, @@ -318,11 +322,24 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + if (DISPLAY_VER(i915) < 11) { + buf[0] = connector->base.hdr_sink_metadata.hdmi_type1.max_cll & 0xFF; + buf[1] = (connector->base.hdr_sink_metadata.hdmi_type1.max_cll & 0xFF00) >> 8; + buf[2] = connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF; + buf[3] = (connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, INTEL_EDP_HDR_CONTENT_LUMINANCE, buf, + sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Content Luminance DPCD reg write failed, err:-%d\n", + ret); + } + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); - panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; -- 2.43.2
[PATCH] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. --v2 -Fix max_cll and max_fall assignment [Jani] -Fix the size sent in drm_dpcd_write [Jani] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 30 ++- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..1b6f14dacf3b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -221,7 +216,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,8 +246,15 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + + if (conn_state->hdr_output_metadata) { + ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE; + } + intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -292,9 +294,11 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); struct drm_luminance_range_info *luminance_range = >base.display_info.luminance_range; int ret; + u8 buf[4]; drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", connector->base.base.id, connector->base.name, @@ -318,11 +322,21 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + buf[0] = connector->base.hdr_sink_metadata.hdmi_type1.max_cll & 0xFF; + buf[1] = (connector->base.hdr_sink_metadata.hdmi_type1.max_cll & 0xFF00) >> 8; + buf[2] = connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF; + buf[3] = (connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF00) >> 8; + + ret = drm_dp_dpcd_write(_dp->aux, INTEL_EDP_HDR_CONTENT_LUMINANCE, buf, + sizeof(buf)); + if (ret < 0) + drm_dbg_kms(>drm, + "Not able to write content luminence to DPCD register err:-%d\n", ret); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); - panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; -- 2.43.2
[PATCH 1/4] drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file
Move intel_hdcp_gsc_message definition into intel_hdcp_gsc.c so that intel_hdcp_gsc_message can be redefined for xe as needed. --v2 -Correct commit message to reflect what patch is actually doing [Arun] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 ++ drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 302bff75b06c..35823e1f65d6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -13,6 +13,12 @@ #include "intel_hdcp_gsc.h" #include "intel_hdcp_gsc_message.h" +struct intel_hdcp_gsc_message { + struct i915_vma *vma; + void *hdcp_cmd_in; + void *hdcp_cmd_out; +}; + bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) { return DISPLAY_VER(i915) >= 14; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h index eba2057c5a9e..5f610df61cc9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h @@ -10,12 +10,7 @@ #include struct drm_i915_private; - -struct intel_hdcp_gsc_message { - struct i915_vma *vma; - void *hdcp_cmd_in; - void *hdcp_cmd_out; -}; +struct intel_hdcp_gsc_message; bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915); ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, -- 2.43.2
[PATCH 2/4] drm/xe/hdcp: Use xe_device struct
Use xe_device struct instead of drm_i915_private so as to not cause confusion and comply with Xe standards as drm_i915_private is xe_device under the hood. --v2 -Fix commit message [Daniele] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 0f11a39333e2..5d1d0054b578 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -3,30 +3,31 @@ * Copyright 2023, Intel Corporation. */ -#include "i915_drv.h" +#include #include "intel_hdcp_gsc.h" +#include "xe_device_types.h" -bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) +bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { return true; } -bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915) +bool intel_hdcp_gsc_check_status(struct xe_device *xe) { return false; } -int intel_hdcp_gsc_init(struct drm_i915_private *i915) +int intel_hdcp_gsc_init(struct xe_device *xe) { - drm_info(>drm, "HDCP support not yet implemented\n"); + drm_dbg_kms(>drm, "HDCP support not yet implemented\n"); return -ENODEV; } -void intel_hdcp_gsc_fini(struct drm_i915_private *i915) +void intel_hdcp_gsc_fini(struct xe_device *xe) { } -ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, +ssize_t intel_hdcp_gsc_msg_send(struct xe_device *xe, u8 *msg_in, size_t msg_in_len, u8 *msg_out, size_t msg_out_len) { -- 2.43.2
[PATCH 4/4] drm/xe/hdcp: Enable HDCP for XE
Enable HDCP for Xe by defining functions which take care of interaction of HDCP as a client with the GSC CS interface. Add intel_hdcp_gsc_message to Makefile and add corresponding changes to xe_hdcp_gsc.c to make it build. --v2 -add kfree at appropriate place [Daniele] -remove useless define [Daniele] -move host session logic to xe_gsc_submit.c [Daniele] -call xe_gsc_check_and_update_pending directly in an if condition [Daniele] -use xe_device instead of drm_i915_private [Daniele] --v3 -use xe prefix for newly exposed function [Daniele] -remove client specific defines from intel_gsc_mtl_header [Daniele] -add missing kfree() [Daniele] -have NULL check for hdcp_message in finish function [Daniele] -dont have too many variable declarations in the same line [Daniele] --v4 -don't point the hdcp_message structure in xe_device to anything until it properly gets initialized [Daniele] --v5 -Squash commits for buildability --v6 -Order includes alphabetically [Lucas] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 202 ++- drivers/gpu/drm/xe/xe_gsc_submit.c | 15 ++ drivers/gpu/drm/xe/xe_gsc_submit.h | 1 + 4 files changed, 214 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index c531210695db..2b654c908ff3 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -254,6 +254,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_global_state.o \ i915-display/intel_gmbus.o \ i915-display/intel_hdcp.o \ + i915-display/intel_hdcp_gsc_message.o \ i915-display/intel_hdmi.o \ i915-display/intel_hotplug.o \ i915-display/intel_hotplug_irq.o \ diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 3af5a86db3aa..dcde1d0ac1f8 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,15 +4,32 @@ */ #include +#include +#include +#include "abi/gsc_command_header_abi.h" #include "intel_hdcp_gsc.h" -#include "xe_device_types.h" +#include "intel_hdcp_gsc_message.h" +#include "xe_bo.h" #include "xe_device.h" -#include "xe_gt.h" +#include "xe_device_types.h" #include "xe_gsc_proxy.h" +#include "xe_gsc_submit.h" +#include "xe_gt.h" +#include "xe_map.h" #include "xe_pm.h" #include "xe_uc_fw.h" +#define HECI_MEADDRESS_HDCP 18 + +struct intel_hdcp_gsc_message { + struct xe_bo *hdcp_bo; + u64 hdcp_cmd_in; + u64 hdcp_cmd_out; +}; + +#define HDCP_GSC_HEADER_SIZE sizeof(struct intel_gsc_mtl_header) + bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { return true; @@ -44,19 +61,194 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) return ret; } +/*This function helps allocate memory for the command that we will send to gsc cs */ +static int intel_hdcp_gsc_initialize_message(struct xe_device *xe, +struct intel_hdcp_gsc_message *hdcp_message) +{ + struct xe_bo *bo = NULL; + u64 cmd_in, cmd_out; + int ret = 0; + + /* allocate object of two page for HDCP command memory and store it */ + xe_device_mem_access_get(xe); + bo = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, PAGE_SIZE * 2, + ttm_bo_type_kernel, + XE_BO_CREATE_SYSTEM_BIT | + XE_BO_CREATE_GGTT_BIT); + + if (IS_ERR(bo)) { + drm_err(>drm, "Failed to allocate bo for HDCP streaming command!\n"); + ret = PTR_ERR(bo); + goto out; + } + + cmd_in = xe_bo_ggtt_addr(bo); + cmd_out = cmd_in + PAGE_SIZE; + xe_map_memset(xe, >vmap, 0, 0, bo->size); + + hdcp_message->hdcp_bo = bo; + hdcp_message->hdcp_cmd_in = cmd_in; + hdcp_message->hdcp_cmd_out = cmd_out; +out: + xe_device_mem_access_put(xe); + return ret; +} + +static int intel_hdcp_gsc_hdcp2_init(struct xe_device *xe) +{ + struct intel_hdcp_gsc_message *hdcp_message; + int ret; + + hdcp_message = kzalloc(sizeof(*hdcp_message), GFP_KERNEL); + + if (!hdcp_message) + return -ENOMEM; + + /* +* NOTE: No need to lock the comp mutex here as it is already +* going to be taken before this function called +*/ + ret = intel_hdcp_gsc_initialize_message(xe, hdcp_message); + if (ret) { + drm_err(>drm, "Could not initialize hdcp_message\n"); + kfree(hdcp_message); + return ret; + } + + xe->
[PATCH 3/4] drm/xe: Use gsc_proxy_init_done to check proxy status
Expose gsc_proxy_init_done so that we can check if gsc proxy has been initialized or not. --v2 -Check if GSC FW is enabled before taking forcewake ref [Daniele] --v3 -Directly call proxy check function inside if condition Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 29 +++- drivers/gpu/drm/xe/xe_gsc_proxy.c| 4 ++-- drivers/gpu/drm/xe/xe_gsc_proxy.h| 1 + 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 5d1d0054b578..3af5a86db3aa 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,8 +4,14 @@ */ #include + #include "intel_hdcp_gsc.h" #include "xe_device_types.h" +#include "xe_device.h" +#include "xe_gt.h" +#include "xe_gsc_proxy.h" +#include "xe_pm.h" +#include "xe_uc_fw.h" bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { @@ -14,7 +20,28 @@ bool intel_hdcp_gsc_cs_required(struct xe_device *xe) bool intel_hdcp_gsc_check_status(struct xe_device *xe) { - return false; + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_gt *gt = tile->media_gt; + bool ret = true; + + if (!xe_uc_fw_is_enabled(>uc.gsc.fw)) + return false; + + xe_pm_runtime_get(xe); + if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC)) { + drm_dbg_kms(>drm, + "failed to get forcewake to check proxy status\n"); + ret = false; + goto out; + } + + if (!xe_gsc_proxy_init_done(>uc.gsc)) + ret = false; + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC); +out: + xe_pm_runtime_put(xe); + return ret; } int intel_hdcp_gsc_init(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index 309ef80e3b95..1ced6b4d4946 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -66,7 +66,7 @@ static inline struct xe_device *kdev_to_xe(struct device *kdev) return dev_get_drvdata(kdev); } -static bool gsc_proxy_init_done(struct xe_gsc *gsc) +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc) { struct xe_gt *gt = gsc_to_gt(gsc); u32 fwsts1 = xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)); @@ -528,7 +528,7 @@ int xe_gsc_proxy_start(struct xe_gsc *gsc) if (err) return err; - if (!gsc_proxy_init_done(gsc)) { + if (!xe_gsc_proxy_init_done(gsc)) { xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n"); return -EIO; } diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.h b/drivers/gpu/drm/xe/xe_gsc_proxy.h index 908f9441f093..c511ade6b863 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.h +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.h @@ -11,6 +11,7 @@ struct xe_gsc; int xe_gsc_proxy_init(struct xe_gsc *gsc); +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc); void xe_gsc_proxy_remove(struct xe_gsc *gsc); int xe_gsc_proxy_start(struct xe_gsc *gsc); -- 2.43.2
[PATCH 1/4] drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file
Move intel_hdcp_gsc_message definition into intel_hdcp_gsc.c so that intel_hdcp_gsc_message can be redefined for xe as needed. --v2 -Correct commit message to reflect what patch is actually doing [Arun] Signed-off-by: Suraj Kandpal Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 ++ drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 302bff75b06c..35823e1f65d6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -13,6 +13,12 @@ #include "intel_hdcp_gsc.h" #include "intel_hdcp_gsc_message.h" +struct intel_hdcp_gsc_message { + struct i915_vma *vma; + void *hdcp_cmd_in; + void *hdcp_cmd_out; +}; + bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) { return DISPLAY_VER(i915) >= 14; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h index eba2057c5a9e..5f610df61cc9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h @@ -10,12 +10,7 @@ #include struct drm_i915_private; - -struct intel_hdcp_gsc_message { - struct i915_vma *vma; - void *hdcp_cmd_in; - void *hdcp_cmd_out; -}; +struct intel_hdcp_gsc_message; bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915); ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, -- 2.43.2
[PATCH 0/4] XE HDCP Enablement
This patch series enables HDCP on XE. Mainly includes rewriting functions that were responsible for sending hdcp messages via gsc cs. Signed-off-by: Suraj Kandpal Acked-by: Lucas De Marchi Suraj Kandpal (4): drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file drm/xe/hdcp: Use xe_device struct drm/xe: Use gsc_proxy_init_done to check proxy status drm/xe/hdcp: Enable HDCP for XE drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 + drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 240 +- drivers/gpu/drm/xe/xe_gsc_proxy.c | 4 +- drivers/gpu/drm/xe/xe_gsc_proxy.h | 1 + drivers/gpu/drm/xe/xe_gsc_submit.c| 15 ++ drivers/gpu/drm/xe/xe_gsc_submit.h| 1 + 8 files changed, 257 insertions(+), 18 deletions(-) -- 2.43.2
[PATCH] drm/i915/dp: Enable AUX based backlight for HDR
As of now whenerver HDR is switched on we use the PWM to change the backlight as opposed to AUX based backlight changes in terms of nits. This patch writes to the appropriate DPCD registers to enable aux based backlight using values in nits. Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_dp_aux_backlight.c | 29 ++- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 4f58efdc688a..14144347f13f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -40,11 +40,6 @@ #include "intel_dp.h" #include "intel_dp_aux_backlight.h" -/* TODO: - * Implement HDR, right now we just implement the bare minimum to bring us back into SDR mode so we - * can make people's backlights work in the mean time - */ - /* * DP AUX registers for Intel's proprietary HDR backlight interface. We define * them here since we'll likely be the only driver to ever use these. @@ -221,7 +216,7 @@ intel_dp_aux_hdr_set_backlight(const struct drm_connector_state *conn_state, u32 struct intel_connector *connector = to_intel_connector(conn_state->connector); struct intel_panel *panel = >panel; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -251,8 +246,15 @@ intel_dp_aux_hdr_enable_backlight(const struct intel_crtc_state *crtc_state, } ctrl = old_ctrl; - if (panel->backlight.edp.intel.sdr_uses_aux) { + if (panel->backlight.edp.intel.sdr_uses_aux || conn_state->hdr_output_metadata) { ctrl |= INTEL_EDP_HDR_TCON_BRIGHTNESS_AUX_ENABLE; + + if (conn_state->hdr_output_metadata) { + ctrl |= INTEL_EDP_HDR_TCON_SEGMENTED_BACKLIGHT_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2084_DECODE_ENABLE; + ctrl |= INTEL_EDP_HDR_TCON_2020_GAMUT_ENABLE; + } + intel_dp_aux_hdr_set_aux_backlight(conn_state, level); } else { u32 pwm_level = intel_backlight_level_to_pwm(connector, level); @@ -292,9 +294,11 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_panel *panel = >panel; + struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); struct drm_luminance_range_info *luminance_range = >base.display_info.luminance_range; int ret; + u8 buf[4]; drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] SDR backlight is controlled through %s\n", connector->base.base.id, connector->base.name, @@ -318,11 +322,20 @@ intel_dp_aux_hdr_setup_backlight(struct intel_connector *connector, enum pipe pi panel->backlight.min = 0; } + buf[0] = panel->backlight.max & 0xFF; + buf[1] = (panel->backlight.max & 0xFF00) >> 8; + buf[2] = (connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF) >> 16; + buf[3] = (connector->base.hdr_sink_metadata.hdmi_type1.max_fall & 0xFF00) >> 24; + + ret = drm_dp_dpcd_write(_dp->aux, INTEL_EDP_HDR_CONTENT_LUMINANCE, buf, + sizeof(buf) != sizeof(buf)); + if (ret) + drm_dbg_kms(>drm, "Not able to write content luminence to DPCD register\n"); + drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] Using AUX HDR interface for backlight control (range %d..%d)\n", connector->base.base.id, connector->base.name, panel->backlight.min, panel->backlight.max); - panel->backlight.level = intel_dp_aux_hdr_get_backlight(connector, pipe); panel->backlight.enabled = panel->backlight.level != 0; -- 2.43.2
[PATCH 3/4] drm/xe: Use gsc_proxy_init_done to check proxy status
Expose gsc_proxy_init_done so that we can check if gsc proxy has been initialized or not. --v2 -Check if GSC FW is enabled before taking forcewake ref [Daniele] --v3 -Directly call forcewake get function inside if condition Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 29 +++- drivers/gpu/drm/xe/xe_gsc_proxy.c| 4 ++-- drivers/gpu/drm/xe/xe_gsc_proxy.h| 1 + 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 5d1d0054b578..3af5a86db3aa 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,8 +4,14 @@ */ #include + #include "intel_hdcp_gsc.h" #include "xe_device_types.h" +#include "xe_device.h" +#include "xe_gt.h" +#include "xe_gsc_proxy.h" +#include "xe_pm.h" +#include "xe_uc_fw.h" bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { @@ -14,7 +20,28 @@ bool intel_hdcp_gsc_cs_required(struct xe_device *xe) bool intel_hdcp_gsc_check_status(struct xe_device *xe) { - return false; + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_gt *gt = tile->media_gt; + bool ret = true; + + if (!xe_uc_fw_is_enabled(>uc.gsc.fw)) + return false; + + xe_pm_runtime_get(xe); + if (xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC)) { + drm_dbg_kms(>drm, + "failed to get forcewake to check proxy status\n"); + ret = false; + goto out; + } + + if (!xe_gsc_proxy_init_done(>uc.gsc)) + ret = false; + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC); +out: + xe_pm_runtime_put(xe); + return ret; } int intel_hdcp_gsc_init(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index 309ef80e3b95..1ced6b4d4946 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -66,7 +66,7 @@ static inline struct xe_device *kdev_to_xe(struct device *kdev) return dev_get_drvdata(kdev); } -static bool gsc_proxy_init_done(struct xe_gsc *gsc) +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc) { struct xe_gt *gt = gsc_to_gt(gsc); u32 fwsts1 = xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)); @@ -528,7 +528,7 @@ int xe_gsc_proxy_start(struct xe_gsc *gsc) if (err) return err; - if (!gsc_proxy_init_done(gsc)) { + if (!xe_gsc_proxy_init_done(gsc)) { xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n"); return -EIO; } diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.h b/drivers/gpu/drm/xe/xe_gsc_proxy.h index 908f9441f093..c511ade6b863 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.h +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.h @@ -11,6 +11,7 @@ struct xe_gsc; int xe_gsc_proxy_init(struct xe_gsc *gsc); +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc); void xe_gsc_proxy_remove(struct xe_gsc *gsc); int xe_gsc_proxy_start(struct xe_gsc *gsc); -- 2.43.2
[PATCH 1/4] drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file
Move intel_hdcp_gsc_message definition into intel_hdcp_gsc.c so that intel_hdcp_gsc_message can be redefined for xe as needed. --v2 -Correct commit message to reflect what patch is actually doing [Arun] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 ++ drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 302bff75b06c..35823e1f65d6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -13,6 +13,12 @@ #include "intel_hdcp_gsc.h" #include "intel_hdcp_gsc_message.h" +struct intel_hdcp_gsc_message { + struct i915_vma *vma; + void *hdcp_cmd_in; + void *hdcp_cmd_out; +}; + bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) { return DISPLAY_VER(i915) >= 14; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h index eba2057c5a9e..5f610df61cc9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h @@ -10,12 +10,7 @@ #include struct drm_i915_private; - -struct intel_hdcp_gsc_message { - struct i915_vma *vma; - void *hdcp_cmd_in; - void *hdcp_cmd_out; -}; +struct intel_hdcp_gsc_message; bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915); ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, -- 2.43.2
[PATCH 1/4] drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file
Move intel_hdcp_gsc_message definition into intel_hdcp_gsc.h so that intel_hdcp_gsc_message can be redefined for xe as needed. --v2 -Correct commit message to reflect what patch is actually doing [Arun] Signed-off-by: Suraj Kandpal --- drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 ++ drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c index 302bff75b06c..35823e1f65d6 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.c @@ -13,6 +13,12 @@ #include "intel_hdcp_gsc.h" #include "intel_hdcp_gsc_message.h" +struct intel_hdcp_gsc_message { + struct i915_vma *vma; + void *hdcp_cmd_in; + void *hdcp_cmd_out; +}; + bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) { return DISPLAY_VER(i915) >= 14; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h index eba2057c5a9e..5f610df61cc9 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp_gsc.h @@ -10,12 +10,7 @@ #include struct drm_i915_private; - -struct intel_hdcp_gsc_message { - struct i915_vma *vma; - void *hdcp_cmd_in; - void *hdcp_cmd_out; -}; +struct intel_hdcp_gsc_message; bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915); ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, -- 2.43.2
[PATCH 4/4] drm/xe/hdcp: Enable HDCP for XE
Enable HDCP for Xe by defining functions which take care of interaction of HDCP as a client with the GSC CS interface. Add intel_hdcp_gsc_message to Makefile and add corresponding changes to xe_hdcp_gsc.c to make it build. --v2 -add kfree at appropriate place [Daniele] -remove useless define [Daniele] -move host session logic to xe_gsc_submit.c [Daniele] -call xe_gsc_check_and_update_pending directly in an if condition [Daniele] -use xe_device instead of drm_i915_private [Daniele] --v3 -use xe prefix for newly exposed function [Daniele] -remove client specific defines from intel_gsc_mtl_header [Daniele] -add missing kfree() [Daniele] -have NULL check for hdcp_message in finish function [Daniele] -dont have too many variable declarations in the same line [Daniele] --v4 -don't point the hdcp_message structure in xe_device to anything until it properly gets initialized [Daniele] --v5 -Squash commits for buildability Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 198 ++- drivers/gpu/drm/xe/xe_gsc_submit.c | 15 ++ drivers/gpu/drm/xe/xe_gsc_submit.h | 1 + 4 files changed, 212 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index c531210695db..2b654c908ff3 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -254,6 +254,7 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_global_state.o \ i915-display/intel_gmbus.o \ i915-display/intel_hdcp.o \ + i915-display/intel_hdcp_gsc_message.o \ i915-display/intel_hdmi.o \ i915-display/intel_hotplug.o \ i915-display/intel_hotplug_irq.o \ diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 0de06e0373ef..bb3bddcd5747 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,14 +4,31 @@ */ #include +#include +#include +#include "abi/gsc_command_header_abi.h" #include "intel_hdcp_gsc.h" +#include "intel_hdcp_gsc_message.h" #include "xe_device_types.h" #include "xe_device.h" #include "xe_gt.h" #include "xe_gsc_proxy.h" #include "xe_pm.h" #include "xe_uc_fw.h" +#include "xe_bo.h" +#include "xe_map.h" +#include "xe_gsc_submit.h" + +#define HECI_MEADDRESS_HDCP 18 + +struct intel_hdcp_gsc_message { + struct xe_bo *hdcp_bo; + u64 hdcp_cmd_in; + u64 hdcp_cmd_out; +}; + +#define HDCP_GSC_HEADER_SIZE sizeof(struct intel_gsc_mtl_header) bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { @@ -45,19 +62,194 @@ bool intel_hdcp_gsc_check_status(struct xe_device *xe) return ret; } +/*This function helps allocate memory for the command that we will send to gsc cs */ +static int intel_hdcp_gsc_initialize_message(struct xe_device *xe, +struct intel_hdcp_gsc_message *hdcp_message) +{ + struct xe_bo *bo = NULL; + u64 cmd_in, cmd_out; + int ret = 0; + + /* allocate object of two page for HDCP command memory and store it */ + xe_device_mem_access_get(xe); + bo = xe_bo_create_pin_map(xe, xe_device_get_root_tile(xe), NULL, PAGE_SIZE * 2, + ttm_bo_type_kernel, + XE_BO_CREATE_SYSTEM_BIT | + XE_BO_CREATE_GGTT_BIT); + + if (IS_ERR(bo)) { + drm_err(>drm, "Failed to allocate bo for HDCP streaming command!\n"); + ret = PTR_ERR(bo); + goto out; + } + + cmd_in = xe_bo_ggtt_addr(bo); + cmd_out = cmd_in + PAGE_SIZE; + xe_map_memset(xe, >vmap, 0, 0, bo->size); + + hdcp_message->hdcp_bo = bo; + hdcp_message->hdcp_cmd_in = cmd_in; + hdcp_message->hdcp_cmd_out = cmd_out; +out: + xe_device_mem_access_put(xe); + return ret; +} + +static int intel_hdcp_gsc_hdcp2_init(struct xe_device *xe) +{ + struct intel_hdcp_gsc_message *hdcp_message; + int ret; + + hdcp_message = kzalloc(sizeof(*hdcp_message), GFP_KERNEL); + + if (!hdcp_message) + return -ENOMEM; + + /* +* NOTE: No need to lock the comp mutex here as it is already +* going to be taken before this function called +*/ + ret = intel_hdcp_gsc_initialize_message(xe, hdcp_message); + if (ret) { + drm_err(>drm, "Could not initialize hdcp_message\n"); + kfree(hdcp_message); + return ret; + } + + xe->display.hdcp.hdcp_message = hdcp_message; + return ret; +} + +static const struct i915_hdcp_ops gsc_hdcp_ops = { + .initiate_hdcp2_session = intel_hdcp_gsc
[PATCH 2/4] drm/xe/hdcp: Use xe_device struct
Use xe_device struct instead of drm_i915_private so as to not cause confusion and comply with Xe standards as drm_i915_private is xe_device under the hood. --v2 -Fix commit message [Daniele] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 15 --- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 0f11a39333e2..5d1d0054b578 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -3,30 +3,31 @@ * Copyright 2023, Intel Corporation. */ -#include "i915_drv.h" +#include #include "intel_hdcp_gsc.h" +#include "xe_device_types.h" -bool intel_hdcp_gsc_cs_required(struct drm_i915_private *i915) +bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { return true; } -bool intel_hdcp_gsc_check_status(struct drm_i915_private *i915) +bool intel_hdcp_gsc_check_status(struct xe_device *xe) { return false; } -int intel_hdcp_gsc_init(struct drm_i915_private *i915) +int intel_hdcp_gsc_init(struct xe_device *xe) { - drm_info(>drm, "HDCP support not yet implemented\n"); + drm_dbg_kms(>drm, "HDCP support not yet implemented\n"); return -ENODEV; } -void intel_hdcp_gsc_fini(struct drm_i915_private *i915) +void intel_hdcp_gsc_fini(struct xe_device *xe) { } -ssize_t intel_hdcp_gsc_msg_send(struct drm_i915_private *i915, u8 *msg_in, +ssize_t intel_hdcp_gsc_msg_send(struct xe_device *xe, u8 *msg_in, size_t msg_in_len, u8 *msg_out, size_t msg_out_len) { -- 2.43.2
[PATCH 3/4] drm/xe: Use gsc_proxy_init_done to check proxy status
Expose gsc_proxy_init_done so that we can check if gsc proxy has been initialized or not. --v2 -Check if GSC FW is enabled before taking forcewake ref [Daniele] Signed-off-by: Suraj Kandpal Reviewed-by: Arun R Murthy Reviewed-by: Daniele Ceraolo Spurio --- drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 30 +++- drivers/gpu/drm/xe/xe_gsc_proxy.c| 4 ++-- drivers/gpu/drm/xe/xe_gsc_proxy.h| 1 + 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c index 5d1d0054b578..0de06e0373ef 100644 --- a/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c +++ b/drivers/gpu/drm/xe/display/xe_hdcp_gsc.c @@ -4,8 +4,14 @@ */ #include + #include "intel_hdcp_gsc.h" #include "xe_device_types.h" +#include "xe_device.h" +#include "xe_gt.h" +#include "xe_gsc_proxy.h" +#include "xe_pm.h" +#include "xe_uc_fw.h" bool intel_hdcp_gsc_cs_required(struct xe_device *xe) { @@ -14,7 +20,29 @@ bool intel_hdcp_gsc_cs_required(struct xe_device *xe) bool intel_hdcp_gsc_check_status(struct xe_device *xe) { - return false; + struct xe_tile *tile = xe_device_get_root_tile(xe); + struct xe_gt *gt = tile->media_gt; + bool ret = true; + + if (!xe_uc_fw_is_enabled(>uc.gsc.fw)) + return false; + + xe_pm_runtime_get(xe); + ret = xe_force_wake_get(gt_to_fw(gt), XE_FW_GSC); + if (ret) { + drm_dbg_kms(>drm, + "failed to get forcewake to check proxy status\n"); + ret = false; + goto out; + } + + if (!xe_gsc_proxy_init_done(>uc.gsc)) + ret = false; + + xe_force_wake_put(gt_to_fw(gt), XE_FW_GSC); +out: + xe_pm_runtime_put(xe); + return ret; } int intel_hdcp_gsc_init(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.c b/drivers/gpu/drm/xe/xe_gsc_proxy.c index 309ef80e3b95..1ced6b4d4946 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.c +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.c @@ -66,7 +66,7 @@ static inline struct xe_device *kdev_to_xe(struct device *kdev) return dev_get_drvdata(kdev); } -static bool gsc_proxy_init_done(struct xe_gsc *gsc) +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc) { struct xe_gt *gt = gsc_to_gt(gsc); u32 fwsts1 = xe_mmio_read32(gt, HECI_FWSTS1(MTL_GSC_HECI1_BASE)); @@ -528,7 +528,7 @@ int xe_gsc_proxy_start(struct xe_gsc *gsc) if (err) return err; - if (!gsc_proxy_init_done(gsc)) { + if (!xe_gsc_proxy_init_done(gsc)) { xe_gt_err(gsc_to_gt(gsc), "GSC FW reports proxy init not completed\n"); return -EIO; } diff --git a/drivers/gpu/drm/xe/xe_gsc_proxy.h b/drivers/gpu/drm/xe/xe_gsc_proxy.h index 908f9441f093..c511ade6b863 100644 --- a/drivers/gpu/drm/xe/xe_gsc_proxy.h +++ b/drivers/gpu/drm/xe/xe_gsc_proxy.h @@ -11,6 +11,7 @@ struct xe_gsc; int xe_gsc_proxy_init(struct xe_gsc *gsc); +bool xe_gsc_proxy_init_done(struct xe_gsc *gsc); void xe_gsc_proxy_remove(struct xe_gsc *gsc); int xe_gsc_proxy_start(struct xe_gsc *gsc); -- 2.43.2
[PATCH 0/4] XE HDCP Enablement
This patch series enables HDCP on XE. Mainly includes rewriting functions that were responsible for sending hdcp messages via gsc cs. Signed-off-by: Suraj Kandpal Suraj Kandpal (4): drm/i915/hdcp: Move intel_hdcp_gsc_message def away from header file drm/xe/hdcp: Use xe_device struct drm/xe: Use gsc_proxy_init_done to check proxy status drm/xe/hdcp: Enable HDCP for XE drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 6 + drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 7 +- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 241 +- drivers/gpu/drm/xe/xe_gsc_proxy.c | 4 +- drivers/gpu/drm/xe/xe_gsc_proxy.h | 1 + drivers/gpu/drm/xe/xe_gsc_submit.c| 15 ++ drivers/gpu/drm/xe/xe_gsc_submit.h| 1 + 8 files changed, 258 insertions(+), 18 deletions(-) -- 2.43.2
[PATCH 5/5] drm/i915/hdcp: Read Rxcaps for robustibility
We see some monitors and docks report incorrect hdcp version and capability in first few reads so we read rx_caps three times before we conclude the monitor's or docks HDCP capability --v2 -Add comment to justify the 3 time read loop for hdcp capability[Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 29 ++-- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 99220f970039..b98a87883fef 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -644,18 +644,29 @@ int _intel_dp_hdcp2_get_capability(struct drm_dp_aux *aux, bool *capable) { u8 rx_caps[3]; - int ret; + int ret, i; *capable = false; - ret = drm_dp_dpcd_read(aux, - DP_HDCP_2_2_REG_RX_CAPS_OFFSET, - rx_caps, HDCP_2_2_RXCAPS_LEN); - if (ret != HDCP_2_2_RXCAPS_LEN) - return ret >= 0 ? -EIO : ret; - if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && - HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) - *capable = true; + /* +* Some HDCP monitors act really shady by not giving the correct hdcp +* capability on the first rx_caps read and usually take an extra read +* to give the capability. We read rx_caps three times before we +* declare a monitor not capable of HDCP 2.2. +*/ + for (i = 0; i < 3; i++) { + ret = drm_dp_dpcd_read(aux, + DP_HDCP_2_2_REG_RX_CAPS_OFFSET, + rx_caps, HDCP_2_2_RXCAPS_LEN); + if (ret != HDCP_2_2_RXCAPS_LEN) + return ret >= 0 ? -EIO : ret; + + if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && + HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) { + *capable = true; + break; + } + } return 0; } -- 2.43.2
[PATCH 3/5] drm/i915/hdcp: Don't enable HDCP1.4 directly from check_link
Whenever LIC fails instead of moving from ENABLED to DESIRED CP property we directly enable HDCP1.4 without informing the userspace of this failure in link integrity check. Now we will just update the value to DESIRED send the event to userspace and then continue with the normal flow of HDCP enablement. Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 1023153ba9d4..321c6dd8dbf5 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1088,15 +1088,9 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - ret = intel_hdcp1_enable(connector); - if (ret) { - drm_err(>drm, "Failed to enable hdcp (%d)\n", ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); out: mutex_unlock(_port->hdcp_mutex); mutex_unlock(>mutex); -- 2.43.2
[PATCH 4/5] drm/i915/hdcp: Allocate stream id after HDCP AKE stage
Allocate stream id after HDCP AKE stage and not before so that it can also be done during link integrity check. Right now for MST scenarios LIC fails after hdcp enablement for this reason. --v2 -no need for else block in prepare_streams function [Ankit] --v3 -remove intel_hdcp argument from required_content_stream function [Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 137 ++ 1 file changed, 65 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 321c6dd8dbf5..9edac27bab26 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,7 +30,7 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 -static int intel_conn_to_vcpi(struct drm_atomic_state *state, +static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { struct drm_dp_mst_topology_mgr *mgr; @@ -43,7 +43,7 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state, return 0; mgr = connector->port->mgr; - drm_modeset_lock(>base.lock, state->acquire_ctx); + drm_modeset_lock(>base.lock, state->base.acquire_ctx); mst_state = to_drm_dp_mst_topology_state(mgr->base.state); payload = drm_atomic_get_mst_payload_state(mst_state, connector->port); if (drm_WARN_ON(mgr->dev, !payload)) @@ -68,19 +68,51 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state, * DP MST topology. Though it is not compulsory, security fw should change its * policy to mark different content_types for different streams. */ -static void -intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) +static int +intel_hdcp_required_content_stream(struct intel_atomic_state *state, + struct intel_digital_port *dig_port) { + struct drm_connector_list_iter conn_iter; + struct intel_digital_port *conn_dig_port; + struct intel_connector *connector; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct hdcp_port_data *data = _port->hdcp_port_data; bool enforce_type0 = false; int k; if (dig_port->hdcp_auth_status) - return; + return 0; + + data->k = 0; if (!dig_port->hdcp_mst_type1_capable) enforce_type0 = true; + drm_connector_list_iter_begin(>drm, _iter); + for_each_intel_connector_iter(connector, _iter) { + if (connector->base.status == connector_status_disconnected) + continue; + + if (!intel_encoder_is_mst(intel_attached_encoder(connector))) + continue; + + conn_dig_port = intel_attached_dig_port(connector); + if (conn_dig_port != dig_port) + continue; + + data->streams[data->k].stream_id = + intel_conn_to_vcpi(state, connector); + data->k++; + + /* if there is only one active stream */ + if (dig_port->dp.active_mst_links <= 1) + break; + } + drm_connector_list_iter_end(_iter); + + if (drm_WARN_ON(>drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0)) + return -EINVAL; + /* * Apply common protection level across all streams in DP MST Topology. * Use highest supported content type for all streams in DP MST Topology. @@ -88,19 +120,25 @@ intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) for (k = 0; k < data->k; k++) data->streams[k].stream_type = enforce_type0 ? DRM_MODE_HDCP_CONTENT_TYPE0 : DRM_MODE_HDCP_CONTENT_TYPE1; + + return 0; } -static void intel_hdcp_prepare_streams(struct intel_connector *connector) +static int intel_hdcp_prepare_streams(struct intel_atomic_state *state, + struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = _port->hdcp_port_data; struct intel_hdcp *hdcp = >hdcp; - if (!intel_encoder_is_mst(intel_attached_encoder(connector))) { - data->streams[0].stream_type = hdcp->content_type; - } else { - intel_hdcp_required_content_stream(dig_port); - } + if (intel_encoder_is_mst(intel_attached_encoder(connector))) + return intel_hdcp_required_content_stream(state, dig_port); + + data->k = 1; + data->streams[0].stream_id = 0; + data->streams[0].stream_type = hdcp->conten
[PATCH 2/5] drm/i915/hdcp: Don't enable HDCP2.2 directly from check_link
Whenever LIC fails instead of moving from ENABLED to DESIRED CP property we directly enable HDCP2.2 without informing the userspace of this failure in link integrity check. Now we will just update the value to DESIRED send the event to userspace and then continue with the normal flow of HDCP enablement. --v2 -Don't change the function prototype in this function [Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 25 ++- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 801b8f0495bb..1023153ba9d4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2068,17 +2068,6 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) drm_dbg_kms(>drm, "HDCP2.2 Downstream topology change\n"); - ret = hdcp2_authenticate_repeater_topology(connector); - if (!ret) { - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_ENABLED, - true); - goto out; - } - drm_dbg_kms(>drm, - "[CONNECTOR:%d:%s] Repeater topology auth failed.(%d)\n", - connector->base.base.id, connector->base.name, - ret); } else { drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", @@ -2095,18 +2084,8 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) goto out; } - ret = _intel_hdcp2_enable(connector); - if (ret) { - drm_dbg_kms(>drm, - "[CONNECTOR:%d:%s] Failed to enable hdcp2.2 (%d)\n", - connector->base.base.id, connector->base.name, - ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, true); out: mutex_unlock(_port->hdcp_mutex); mutex_unlock(>mutex); -- 2.43.2
[PATCH 1/5] drm/i915/hdcp: Extract hdcp structure from correct connector
Currently intel_hdcp is not being extracted from primary connector this patch fixes that. Fixes: 524240b231ea ("drm/i915/hdcp: Propagate aux info in DP HDCP functions") Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 16ed489e09ec..99220f970039 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -395,7 +395,9 @@ intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector, const struct hdcp2_dp_msg_data *hdcp2_msg_data) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct intel_hdcp *hdcp = >hdcp; + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_dp *dp = _port->dp; + struct intel_hdcp *hdcp = >attached_connector->hdcp; u8 msg_id = hdcp2_msg_data->msg_id; int ret, timeout; bool msg_ready = false; @@ -511,8 +513,9 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector, { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_hdcp *hdcp = >hdcp; struct drm_dp_aux *aux = _port->dp.aux; + struct intel_dp *dp = _port->dp; + struct intel_hdcp *hdcp = >attached_connector->hdcp; unsigned int offset; u8 *byte = buf; ssize_t ret, bytes_to_recv, len; -- 2.43.2
[PATCH 0/5] HDCP MST Type1 fixes
We were seeing a blank screen whenever Type1 content was played. This was due to extra timing which was taken as we had moved to remote read and writes previously for MST scenario, which in turn was done as we were not able to do direct read and writes to the immediate downstream device. The correct flow should be that we talk only to the immediate downstream device and the rest needs to be taken care by that device. With this patch series we move back to direct reads and writes, fix the fastset setting because of which direct reads and writes to HDCP related DPCD register stopped working, derive hdcp structure correctly and increase robustability if rxcaps HDCP capability reporting. Rebased on latest commits. Signed-off-by: Suraj Kandpal Suraj Kandpal (5): drm/i915/hdcp: Extract hdcp structure from correct connector drm/i915/hdcp: Don't enable HDCP2.2 directly from check_link drm/i915/hdcp: Don't enable HDCP1.4 directly from check_link drm/i915/hdcp: Allocate stream id after HDCP AKE stage drm/i915/hdcp: Read Rxcaps for robustibility drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 36 ++-- drivers/gpu/drm/i915/display/intel_hdcp.c| 174 --- 2 files changed, 95 insertions(+), 115 deletions(-) -- 2.43.2
[PATCH 06/13] drm/i915/hdcp: Add new remote capability check shim function
Create a remote HDCP capability shim function which can read the remote monitor HDCP capability when in MST configuration. --v2 -Add an assertion to make sure only mst encoder call this remote_cap function [Ankit] --v3 -rename remote_hdcp_cap to remote_hdcp_capability [Jani] --v4 -fix hdcp2_prerequisite check condition -Move intel_dp_hdcp_get_remote_capability to dp_mst shim instead of having it in dp shim [Ankit] Signed-off-by: Suraj Kandpal --- .../drm/i915/display/intel_display_types.h| 4 +++ drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 27 +++ drivers/gpu/drm/i915/display/intel_hdcp.c | 16 +++ drivers/gpu/drm/i915/display/intel_hdcp.h | 3 +++ 4 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b6f86129c0bc..8ce986fadd9a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -531,6 +531,10 @@ struct intel_hdcp_shim { /* HDCP2.2 Link Integrity Check */ int (*check_2_2_link)(struct intel_digital_port *dig_port, struct intel_connector *connector); + + /* HDCP remote sink cap */ + int (*get_remote_hdcp_capability)(struct intel_connector *connector, + bool *hdcp_capable, bool *hdcp2_capable); }; struct intel_hdcp { diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index bf90e9024feb..eab6e9fab4e6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -672,6 +672,32 @@ int intel_dp_hdcp2_get_capability(struct intel_connector *connector, return _intel_dp_hdcp2_get_capability(aux, capable); } +static +int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_dp_aux *aux = >port->aux; + u8 bcaps; + int ret; + + if (!intel_encoder_is_mst(connector->encoder)) + return -EINVAL; + + ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); + if (ret) + return ret; + + ret = intel_dp_hdcp_read_bcaps(aux, i915, ); + if (ret) + return ret; + + *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE; + + return 0; +} + static const struct intel_hdcp_shim intel_dp_hdcp_shim = { .write_an_aksv = intel_dp_hdcp_write_an_aksv, .read_bksv = intel_dp_hdcp_read_bksv, @@ -820,6 +846,7 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = { .stream_2_2_encryption = intel_dp_mst_hdcp2_stream_encryption, .check_2_2_link = intel_dp_mst_hdcp2_check_link, .hdcp_2_2_get_capability = intel_dp_hdcp2_get_capability, + .get_remote_hdcp_capability = intel_dp_hdcp_get_remote_capability, .protocol = HDCP_PROTOCOL_DP, }; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index c1a32f9f1199..801b8f0495bb 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -205,6 +205,22 @@ bool intel_hdcp2_get_capability(struct intel_connector *connector) return capable; } +void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) +{ + struct intel_hdcp *hdcp = >hdcp; + + if (!hdcp->shim->get_remote_hdcp_capability) + return; + + hdcp->shim->get_remote_hdcp_capability(connector, hdcp_capable, + hdcp2_capable); + + if (!intel_hdcp2_prerequisite(connector)) + *hdcp2_capable = false; +} + static bool intel_hdcp_in_use(struct drm_i915_private *i915, enum transcoder cpu_transcoder, enum port port) { diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index aeefb3c13d2c..477f2d2bb120 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -40,6 +40,9 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, bool is_hdcp_supported(struct drm_i915_private *i915, enum port port); bool intel_hdcp_get_capability(struct intel_connector *connector); bool intel_hdcp2_get_capability(struct intel_connector *connector); +void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable); void intel_hdcp_component_init(struct
[PATCH 12/13] drm/i915/hdcp: Allocate stream id after HDCP AKE stage
Allocate stream id after HDCP AKE stage and not before so that it can also be done during link integrity check. Right now for MST scenarios LIC fails after hdcp enablement for this reason. --v2 -no need for else block in prepare_streams function [Ankit] --v3 -remove intel_hdcp argument from required_content_stream function [Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 137 ++ 1 file changed, 65 insertions(+), 72 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 321c6dd8dbf5..9edac27bab26 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -30,7 +30,7 @@ #define KEY_LOAD_TRIES 5 #define HDCP2_LC_RETRY_CNT 3 -static int intel_conn_to_vcpi(struct drm_atomic_state *state, +static int intel_conn_to_vcpi(struct intel_atomic_state *state, struct intel_connector *connector) { struct drm_dp_mst_topology_mgr *mgr; @@ -43,7 +43,7 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state, return 0; mgr = connector->port->mgr; - drm_modeset_lock(>base.lock, state->acquire_ctx); + drm_modeset_lock(>base.lock, state->base.acquire_ctx); mst_state = to_drm_dp_mst_topology_state(mgr->base.state); payload = drm_atomic_get_mst_payload_state(mst_state, connector->port); if (drm_WARN_ON(mgr->dev, !payload)) @@ -68,19 +68,51 @@ static int intel_conn_to_vcpi(struct drm_atomic_state *state, * DP MST topology. Though it is not compulsory, security fw should change its * policy to mark different content_types for different streams. */ -static void -intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) +static int +intel_hdcp_required_content_stream(struct intel_atomic_state *state, + struct intel_digital_port *dig_port) { + struct drm_connector_list_iter conn_iter; + struct intel_digital_port *conn_dig_port; + struct intel_connector *connector; + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); struct hdcp_port_data *data = _port->hdcp_port_data; bool enforce_type0 = false; int k; if (dig_port->hdcp_auth_status) - return; + return 0; + + data->k = 0; if (!dig_port->hdcp_mst_type1_capable) enforce_type0 = true; + drm_connector_list_iter_begin(>drm, _iter); + for_each_intel_connector_iter(connector, _iter) { + if (connector->base.status == connector_status_disconnected) + continue; + + if (!intel_encoder_is_mst(intel_attached_encoder(connector))) + continue; + + conn_dig_port = intel_attached_dig_port(connector); + if (conn_dig_port != dig_port) + continue; + + data->streams[data->k].stream_id = + intel_conn_to_vcpi(state, connector); + data->k++; + + /* if there is only one active stream */ + if (dig_port->dp.active_mst_links <= 1) + break; + } + drm_connector_list_iter_end(_iter); + + if (drm_WARN_ON(>drm, data->k > INTEL_NUM_PIPES(i915) || data->k == 0)) + return -EINVAL; + /* * Apply common protection level across all streams in DP MST Topology. * Use highest supported content type for all streams in DP MST Topology. @@ -88,19 +120,25 @@ intel_hdcp_required_content_stream(struct intel_digital_port *dig_port) for (k = 0; k < data->k; k++) data->streams[k].stream_type = enforce_type0 ? DRM_MODE_HDCP_CONTENT_TYPE0 : DRM_MODE_HDCP_CONTENT_TYPE1; + + return 0; } -static void intel_hdcp_prepare_streams(struct intel_connector *connector) +static int intel_hdcp_prepare_streams(struct intel_atomic_state *state, + struct intel_connector *connector) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct hdcp_port_data *data = _port->hdcp_port_data; struct intel_hdcp *hdcp = >hdcp; - if (!intel_encoder_is_mst(intel_attached_encoder(connector))) { - data->streams[0].stream_type = hdcp->content_type; - } else { - intel_hdcp_required_content_stream(dig_port); - } + if (intel_encoder_is_mst(intel_attached_encoder(connector))) + return intel_hdcp_required_content_stream(state, dig_port); + + data->k = 1; + data->streams[0].stream_id = 0; + data->streams[0].stream_type = hdcp->conten
[PATCH 07/13] drm/i915/hdcp: HDCP Capability for the downstream device
Currently we are only checking capability of remote device and not immediate downstream device but during capability check we need are concerned with only the HDCP capability of downstream device. During i915_display_info reporting we need HDCP Capability for both the monitors and downstream branch device if any this patch adds that. --v2 -Use MST Hub HDCP version [Ankit] --v3 -Redefined how we seprate remote and direct read to make sure HDMI shim functions are not touched [Ankit] --v4 - Fix the conditions so that hdcp_info with remote_req true is sent only when encoder is mst [Ankit] --v5 -No need to have the MST Hub version in i915_hdcp_sink_capability[Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_debugfs.c | 21 ++- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index d8f1a23ac2b1..b99c024b0934 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -188,7 +188,8 @@ static void intel_panel_info(struct seq_file *m, } static void intel_hdcp_info(struct seq_file *m, - struct intel_connector *intel_connector) + struct intel_connector *intel_connector, + bool remote_req) { bool hdcp_cap, hdcp2_cap; @@ -197,8 +198,14 @@ static void intel_hdcp_info(struct seq_file *m, goto out; } - hdcp_cap = intel_hdcp_get_capability(intel_connector); - hdcp2_cap = intel_hdcp2_get_capability(intel_connector); + if (remote_req) { + intel_hdcp_get_remote_capability(intel_connector, +_cap, +_cap); + } else { + hdcp_cap = intel_hdcp_get_capability(intel_connector); + hdcp2_cap = intel_hdcp2_get_capability(intel_connector); + } if (hdcp_cap) seq_puts(m, "HDCP1.4 "); @@ -285,7 +292,11 @@ static void intel_connector_info(struct seq_file *m, } seq_puts(m, "\tHDCP version: "); - intel_hdcp_info(m, intel_connector); + if (intel_encoder_is_mst(encoder)) { + intel_hdcp_info(m, intel_connector, true); + seq_puts(m, "\tMST Hub HDCP version: "); + } + intel_hdcp_info(m, intel_connector, false); seq_printf(m, "\tmax bpc: %u\n", connector->display_info.bpc); @@ -1131,7 +1142,7 @@ static int i915_hdcp_sink_capability_show(struct seq_file *m, void *data) seq_printf(m, "%s:%d HDCP version: ", connector->base.name, connector->base.base.id); - intel_hdcp_info(m, connector); + intel_hdcp_info(m, connector, false); out: drm_modeset_unlock(>drm.mode_config.connection_mutex); -- 2.43.2
[PATCH 11/13] drm/i915/hdcp: Don't enable HDCP1.4 directly from check_link
Whenever LIC fails instead of moving from ENABLED to DESIRED CP property we directly enable HDCP1.4 without informing the userspace of this failure in link integrity check. Now we will just update the value to DESIRED send the event to userspace and then continue with the normal flow of HDCP enablement. Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 1023153ba9d4..321c6dd8dbf5 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -1088,15 +1088,9 @@ static int intel_hdcp_check_link(struct intel_connector *connector) goto out; } - ret = intel_hdcp1_enable(connector); - if (ret) { - drm_err(>drm, "Failed to enable hdcp (%d)\n", ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, + true); out: mutex_unlock(_port->hdcp_mutex); mutex_unlock(>mutex); -- 2.43.2
[PATCH 13/13] drm/i915/hdcp: Read Rxcaps for robustibility
We see some monitors and docks report incorrect hdcp version and capability in first few reads so we read rx_caps three times before we conclude the monitor's or docks HDCP capability --v2 -Add comment to justify the 3 time read loop for hdcp capability[Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 29 ++-- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 99220f970039..b98a87883fef 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -644,18 +644,29 @@ int _intel_dp_hdcp2_get_capability(struct drm_dp_aux *aux, bool *capable) { u8 rx_caps[3]; - int ret; + int ret, i; *capable = false; - ret = drm_dp_dpcd_read(aux, - DP_HDCP_2_2_REG_RX_CAPS_OFFSET, - rx_caps, HDCP_2_2_RXCAPS_LEN); - if (ret != HDCP_2_2_RXCAPS_LEN) - return ret >= 0 ? -EIO : ret; - if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && - HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) - *capable = true; + /* +* Some HDCP monitors act really shady by not giving the correct hdcp +* capability on the first rx_caps read and usually take an extra read +* to give the capability. We read rx_caps three times before we +* declare a monitor not capable of HDCP 2.2. +*/ + for (i = 0; i < 3; i++) { + ret = drm_dp_dpcd_read(aux, + DP_HDCP_2_2_REG_RX_CAPS_OFFSET, + rx_caps, HDCP_2_2_RXCAPS_LEN); + if (ret != HDCP_2_2_RXCAPS_LEN) + return ret >= 0 ? -EIO : ret; + + if (rx_caps[0] == HDCP_2_2_RX_CAPS_VERSION_VAL && + HDCP_2_2_DP_HDCP_CAPABLE(rx_caps[2])) { + *capable = true; + break; + } + } return 0; } -- 2.43.2
[PATCH 09/13] drm/i915/hdcp: Extract hdcp structure from correct connector
Currently intel_hdcp is not being extracted from primary connector this patch fixes that. Fixes: 524240b231ea ("drm/i915/hdcp: Propagate aux info in DP HDCP functions") Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 16ed489e09ec..99220f970039 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -395,7 +395,9 @@ intel_dp_hdcp2_wait_for_msg(struct intel_connector *connector, const struct hdcp2_dp_msg_data *hdcp2_msg_data) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct intel_hdcp *hdcp = >hdcp; + struct intel_digital_port *dig_port = intel_attached_dig_port(connector); + struct intel_dp *dp = _port->dp; + struct intel_hdcp *hdcp = >attached_connector->hdcp; u8 msg_id = hdcp2_msg_data->msg_id; int ret, timeout; bool msg_ready = false; @@ -511,8 +513,9 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector, { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - struct intel_hdcp *hdcp = >hdcp; struct drm_dp_aux *aux = _port->dp.aux; + struct intel_dp *dp = _port->dp; + struct intel_hdcp *hdcp = >attached_connector->hdcp; unsigned int offset; u8 *byte = buf; ssize_t ret, bytes_to_recv, len; -- 2.43.2
[PATCH 10/13] drm/i915/hdcp: Don't enable HDCP2.2 directly from check_link
Whenever LIC fails instead of moving from ENABLED to DESIRED CP property we directly enable HDCP2.2 without informing the userspace of this failure in link integrity check. Now we will just update the value to DESIRED send the event to userspace and then continue with the normal flow of HDCP enablement. --v2 -Don't change the function prototype in this function [Ankit] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 25 ++- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 801b8f0495bb..1023153ba9d4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -2068,17 +2068,6 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) drm_dbg_kms(>drm, "HDCP2.2 Downstream topology change\n"); - ret = hdcp2_authenticate_repeater_topology(connector); - if (!ret) { - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_ENABLED, - true); - goto out; - } - drm_dbg_kms(>drm, - "[CONNECTOR:%d:%s] Repeater topology auth failed.(%d)\n", - connector->base.base.id, connector->base.name, - ret); } else { drm_dbg_kms(>drm, "[CONNECTOR:%d:%s] HDCP2.2 link failed, retrying auth\n", @@ -2095,18 +2084,8 @@ static int intel_hdcp2_check_link(struct intel_connector *connector) goto out; } - ret = _intel_hdcp2_enable(connector); - if (ret) { - drm_dbg_kms(>drm, - "[CONNECTOR:%d:%s] Failed to enable hdcp2.2 (%d)\n", - connector->base.base.id, connector->base.name, - ret); - intel_hdcp_update_value(connector, - DRM_MODE_CONTENT_PROTECTION_DESIRED, - true); - goto out; - } - + intel_hdcp_update_value(connector, + DRM_MODE_CONTENT_PROTECTION_DESIRED, true); out: mutex_unlock(_port->hdcp_mutex); mutex_unlock(>mutex); -- 2.43.2
[PATCH 08/13] drm/i915/hdcp: Remove additional timing for reading mst hdcp message
Now that we have moved back to direct reads the additional timing is not required hence this can be removed. --v2 -Add Fixes tag [Ankit] Fixes: 3974f9c17bb9 ("drm/i915/hdcp: Adjust timeout for read in DPMST Scenario") Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 9 ++--- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index eab6e9fab4e6..16ed489e09ec 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -555,13 +555,8 @@ int intel_dp_hdcp2_read_msg(struct intel_connector *connector, /* Entire msg read timeout since initiate of msg read */ if (bytes_to_recv == size - 1 && hdcp2_msg_data->msg_read_timeout > 0) { - if (intel_encoder_is_mst(connector->encoder)) - msg_end = ktime_add_ms(ktime_get_raw(), - hdcp2_msg_data->msg_read_timeout * - connector->port->parent->num_ports); - else - msg_end = ktime_add_ms(ktime_get_raw(), - hdcp2_msg_data->msg_read_timeout); + msg_end = ktime_add_ms(ktime_get_raw(), + hdcp2_msg_data->msg_read_timeout); } ret = drm_dp_dpcd_read(aux, offset, -- 2.43.2
[PATCH 05/13] drm/i915/hdcp: Rename hdcp capable functions
Rename hdcp_capable and hdcp_2_2_capable to hdcp_get_capability and hdcp_2_2_get_capability to properly reflect what these functions are doing. Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_debugfs.c | 4 ++-- .../drm/i915/display/intel_display_types.h| 8 +++ drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 22 +-- drivers/gpu/drm/i915/display/intel_hdcp.c | 18 +++ drivers/gpu/drm/i915/display/intel_hdcp.h | 4 ++-- drivers/gpu/drm/i915/display/intel_hdmi.c | 6 ++--- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index a962b48bcf13..d8f1a23ac2b1 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -197,8 +197,8 @@ 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); + hdcp_cap = intel_hdcp_get_capability(intel_connector); + hdcp2_cap = intel_hdcp2_get_capability(intel_connector); if (hdcp_cap) seq_puts(m, "HDCP1.4 "); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 578763e202c0..b6f86129c0bc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -498,15 +498,15 @@ struct intel_hdcp_shim { struct intel_connector *connector); /* Detects panel's hdcp capability. This is optional for HDMI. */ - int (*hdcp_capable)(struct intel_digital_port *dig_port, - bool *hdcp_capable); + int (*hdcp_get_capability)(struct intel_digital_port *dig_port, + bool *hdcp_capable); /* HDCP adaptation(DP/HDMI) required on the port */ enum hdcp_wired_protocol protocol; /* Detects whether sink is HDCP2.2 capable */ - int (*hdcp_2_2_capable)(struct intel_connector *connector, - bool *capable); + int (*hdcp_2_2_get_capability)(struct intel_connector *connector, + bool *capable); /* Write HDCP2.2 messages */ int (*write_2_2_msg)(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 5394391acbe1..bf90e9024feb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -269,8 +269,8 @@ bool intel_dp_hdcp_check_link(struct intel_digital_port *dig_port, } static -int intel_dp_hdcp_capable(struct intel_digital_port *dig_port, - bool *hdcp_capable) +int intel_dp_hdcp_get_capability(struct intel_digital_port *dig_port, +bool *hdcp_capable) { struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; @@ -642,8 +642,8 @@ int intel_dp_hdcp2_check_link(struct intel_digital_port *dig_port, } static -int _intel_dp_hdcp2_capable(struct drm_dp_aux *aux, - bool *capable) +int _intel_dp_hdcp2_get_capability(struct drm_dp_aux *aux, + bool *capable) { u8 rx_caps[3]; int ret; @@ -663,13 +663,13 @@ int _intel_dp_hdcp2_capable(struct drm_dp_aux *aux, } static -int intel_dp_hdcp2_capable(struct intel_connector *connector, - bool *capable) +int intel_dp_hdcp2_get_capability(struct intel_connector *connector, + bool *capable) { struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_dp_aux *aux = _port->dp.aux; - return _intel_dp_hdcp2_capable(aux, capable); + return _intel_dp_hdcp2_get_capability(aux, capable); } static const struct intel_hdcp_shim intel_dp_hdcp_shim = { @@ -683,12 +683,12 @@ static const struct intel_hdcp_shim intel_dp_hdcp_shim = { .read_v_prime_part = intel_dp_hdcp_read_v_prime_part, .toggle_signalling = intel_dp_hdcp_toggle_signalling, .check_link = intel_dp_hdcp_check_link, - .hdcp_capable = intel_dp_hdcp_capable, + .hdcp_get_capability = intel_dp_hdcp_get_capability, .write_2_2_msg = intel_dp_hdcp2_write_msg, .read_2_2_msg = intel_dp_hdcp2_read_msg, .config_stream_type = intel_dp_hdcp2_config_stream_type, .check_2_2_link = intel_dp_hdcp2_check_link, - .hdcp_2_2_capable = intel_dp_hdcp2_capable, + .hdcp_2_2_get_capability = intel_dp_hdcp2_get_capability, .protocol = HDCP_PROTOCOL_DP, }; @@ -813,13 +813,13 @@ static const struct
[PATCH 02/13] drm/i915/hdcp: Move source hdcp2 checks into its own function
Move checks on the source side for HDCP2.2 into its own function so that they can be used in the HDCP remote capability check function. Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_hdcp.c | 20 +--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index c3e692e7f790..4593ac10e2fa 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -160,12 +160,14 @@ bool intel_hdcp_capable(struct intel_connector *connector) return capable; } -/* Is HDCP2.2 capable on Platform and Sink */ -bool intel_hdcp2_capable(struct intel_connector *connector) +/* + * Check if the source has all the building blocks ready to make + * HDCP 2.2 work + */ +static bool intel_hdcp2_prerequisite(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct intel_hdcp *hdcp = >hdcp; - bool capable = false; /* I915 support for HDCP2.2 */ if (!hdcp->hdcp2_supported) @@ -185,6 +187,18 @@ bool intel_hdcp2_capable(struct intel_connector *connector) } mutex_unlock(>display.hdcp.hdcp_mutex); + return true; +} + +/* Is HDCP2.2 capable on Platform and Sink */ +bool intel_hdcp2_capable(struct intel_connector *connector) +{ + struct intel_hdcp *hdcp = >hdcp; + bool capable = false; + + if (!intel_hdcp2_prerequisite(connector)) + return false; + /* Sink's capability for HDCP2.2 */ hdcp->shim->hdcp_2_2_capable(connector, ); -- 2.43.2
[PATCH 06/13] drm/i915/hdcp: Add new remote capability check shim function
Create a remote HDCP capability shim function which can read the remote monitor HDCP capability when in MST configuration. --v2 -Add an assertion to make sure only mst encoder call this remote_cap function [Ankit] --v3 -rename remote_hdcp_cap to remote_hdcp_capability [Jani] Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- .../drm/i915/display/intel_display_types.h| 4 +++ drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 27 +++ drivers/gpu/drm/i915/display/intel_hdcp.c | 16 +++ drivers/gpu/drm/i915/display/intel_hdcp.h | 3 +++ 4 files changed, 50 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b6f86129c0bc..8ce986fadd9a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -531,6 +531,10 @@ struct intel_hdcp_shim { /* HDCP2.2 Link Integrity Check */ int (*check_2_2_link)(struct intel_digital_port *dig_port, struct intel_connector *connector); + + /* HDCP remote sink cap */ + int (*get_remote_hdcp_capability)(struct intel_connector *connector, + bool *hdcp_capable, bool *hdcp2_capable); }; struct intel_hdcp { diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index bf90e9024feb..eab6e9fab4e6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -672,6 +672,32 @@ int intel_dp_hdcp2_get_capability(struct intel_connector *connector, return _intel_dp_hdcp2_get_capability(aux, capable); } +static +int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_dp_aux *aux = >port->aux; + u8 bcaps; + int ret; + + if (!intel_encoder_is_mst(connector->encoder)) + return -EINVAL; + + ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); + if (ret) + return ret; + + ret = intel_dp_hdcp_read_bcaps(aux, i915, ); + if (ret) + return ret; + + *hdcp_capable = bcaps & DP_BCAPS_HDCP_CAPABLE; + + return 0; +} + static const struct intel_hdcp_shim intel_dp_hdcp_shim = { .write_an_aksv = intel_dp_hdcp_write_an_aksv, .read_bksv = intel_dp_hdcp_read_bksv, @@ -820,6 +846,7 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim = { .stream_2_2_encryption = intel_dp_mst_hdcp2_stream_encryption, .check_2_2_link = intel_dp_mst_hdcp2_check_link, .hdcp_2_2_get_capability = intel_dp_hdcp2_get_capability, + .get_remote_hdcp_capability = intel_dp_hdcp_get_remote_capability, .protocol = HDCP_PROTOCOL_DP, }; diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index c1a32f9f1199..801b8f0495bb 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -205,6 +205,22 @@ bool intel_hdcp2_get_capability(struct intel_connector *connector) return capable; } +void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable) +{ + struct intel_hdcp *hdcp = >hdcp; + + if (!hdcp->shim->get_remote_hdcp_capability) + return; + + hdcp->shim->get_remote_hdcp_capability(connector, hdcp_capable, + hdcp2_capable); + + if (!intel_hdcp2_prerequisite(connector)) + *hdcp2_capable = false; +} + static bool intel_hdcp_in_use(struct drm_i915_private *i915, enum transcoder cpu_transcoder, enum port port) { diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index aeefb3c13d2c..477f2d2bb120 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -40,6 +40,9 @@ void intel_hdcp_update_pipe(struct intel_atomic_state *state, bool is_hdcp_supported(struct drm_i915_private *i915, enum port port); bool intel_hdcp_get_capability(struct intel_connector *connector); bool intel_hdcp2_get_capability(struct intel_connector *connector); +void intel_hdcp_get_remote_capability(struct intel_connector *connector, + bool *hdcp_capable, + bool *hdcp2_capable); void intel_hdcp_component_init(struct drm_i915_private *i915); void intel_hdcp_component_fini(struct drm_i915_private *i915); void intel_hdcp
[PATCH 04/13] drm/i915/hdcp: Pass drm_dp_aux to read_bcaps function
Pass drm_dp_aux to intel_dp_hdcp_read_bcaps function so as to aid in reading the bcaps for the remote monitor later on. Signed-off-by: Suraj Kandpal Reviewed-by: Ankit Nautiyal --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index 6767b5338ae7..5394391acbe1 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -125,13 +125,13 @@ static int intel_dp_hdcp_read_bstatus(struct intel_digital_port *dig_port, } static -int intel_dp_hdcp_read_bcaps(struct intel_digital_port *dig_port, +int intel_dp_hdcp_read_bcaps(struct drm_dp_aux *aux, +struct drm_i915_private *i915, u8 *bcaps) { - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; - ret = drm_dp_dpcd_read(_port->dp.aux, DP_AUX_HDCP_BCAPS, + ret = drm_dp_dpcd_read(aux, DP_AUX_HDCP_BCAPS, bcaps, 1); if (ret != 1) { drm_dbg_kms(>drm, @@ -146,10 +146,11 @@ static int intel_dp_hdcp_repeater_present(struct intel_digital_port *dig_port, bool *repeater_present) { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; u8 bcaps; - ret = intel_dp_hdcp_read_bcaps(dig_port, ); + ret = intel_dp_hdcp_read_bcaps(_port->dp.aux, i915, ); if (ret) return ret; @@ -271,10 +272,11 @@ static int intel_dp_hdcp_capable(struct intel_digital_port *dig_port, bool *hdcp_capable) { + struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); ssize_t ret; u8 bcaps; - ret = intel_dp_hdcp_read_bcaps(dig_port, ); + ret = intel_dp_hdcp_read_bcaps(_port->dp.aux, i915, ); if (ret) return ret; -- 2.43.2