From 07cc32ecc6f393f416589f90f30542bfa7a9891d Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Mon, 26 May 2025 15:05:01 +0300 Subject: drm/panelreplay: Panel Replay capability DPCD register definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new definition for size of Panel Replay DPCD capability registers area. Rename existing definitions to group capability registers together. Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Acked-by: Maarten Lankhorst Link: https://lore.kernel.org/r/20250526120512.1702815-2-jouni.hogander@intel.com --- include/drm/display/drm_dp.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 3001c0b6e7bb..3371e2edd9e9 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -547,16 +547,18 @@ /* DFP Capability Extension */ #define DP_DFP_CAPABILITY_EXTENSION_SUPPORT 0x0a3 /* 2.0 */ -#define DP_PANEL_REPLAY_CAP 0x0b0 /* DP 2.0 */ +#define DP_PANEL_REPLAY_CAP_SUPPORT 0x0b0 /* DP 2.0 */ # define DP_PANEL_REPLAY_SUPPORT (1 << 0) # define DP_PANEL_REPLAY_SU_SUPPORT (1 << 1) # define DP_PANEL_REPLAY_EARLY_TRANSPORT_SUPPORT (1 << 2) /* eDP 1.5 */ -#define DP_PANEL_PANEL_REPLAY_CAPABILITY 0xb1 -# define DP_PANEL_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +#define DP_PANEL_REPLAY_CAP_SIZE 7 -#define DP_PANEL_PANEL_REPLAY_X_GRANULARITY 0xb2 -#define DP_PANEL_PANEL_REPLAY_Y_GRANULARITY 0xb4 +#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 +# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) + +#define DP_PANEL_REPLAY_CAP_X_GRANULARITY 0xb2 +#define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4 /* Link Configuration */ #define DP_LINK_BW_SET 0x100 -- cgit v1.2.3 From 3e61b092e61d8f7f0b882f07ede9a0a553197e21 Mon Sep 17 00:00:00 2001 From: Jouni Högander Date: Mon, 26 May 2025 15:05:02 +0300 Subject: drm/dp: Add Panel Replay capability bits from DP2.1 specification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PANEL REPLAY CAPABILITY register (0xb1) bits. v3: - added DP_DSC_DECODE_CAPABILITY definitions - use defined shift instead of hardcoded value v2: comment about DP2.1 changed as DP2.1a Signed-off-by: Jouni Högander Reviewed-by: Ankit Nautiyal Acked-by: Maarten Lankhorst Link: https://lore.kernel.org/r/20250526120512.1702815-3-jouni.hogander@intel.com --- include/drm/display/drm_dp.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index 3371e2edd9e9..811e9238a77c 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -554,8 +554,18 @@ #define DP_PANEL_REPLAY_CAP_SIZE 7 -#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 -# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +#define DP_PANEL_REPLAY_CAP_CAPABILITY 0xb1 +# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT 1 /* DP 2.1a */ +# define DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_MASK (3 << DP_PANEL_REPLAY_DSC_DECODE_CAPABILITY_IN_PR_SHIFT) +# define DP_DSC_DECODE_CAPABILITY_IN_PR_SUPPORTED 0x00 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_FULL_FRAME_ONLY 0x01 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_NOT_SUPPORTED 0x02 +# define DP_DSC_DECODE_CAPABILITY_IN_PR_RESERVED 0x03 +# define DP_PANEL_REPLAY_ASYNC_VIDEO_TIMING_NOT_SUPPORTED_IN_PR (1 << 3) +# define DP_PANEL_REPLAY_DSC_CRC_OF_MULTIPLE_SUS_SUPPORTED (1 << 4) +# define DP_PANEL_REPLAY_SU_GRANULARITY_REQUIRED (1 << 5) +# define DP_PANEL_REPLAY_SU_Y_GRANULARITY_EXTENDED_CAPABILITY_SUPPORTED (1 << 6) +# define DP_PANEL_REPLAY_LINK_OFF_SUPPORTED_IN_PR_AFTER_ADAPTIVE_SYNC_SDP (1 << 7) #define DP_PANEL_REPLAY_CAP_X_GRANULARITY 0xb2 #define DP_PANEL_REPLAY_CAP_Y_GRANULARITY 0xb4 -- cgit v1.2.3 From 0b4aa85e8981198e23a68d50ee3c490ccd7f8311 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Thu, 5 Jun 2025 11:28:48 +0300 Subject: drm/edid: Add support for quirks visible to DRM core and drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for EDID based quirks which can be queried outside of the EDID parser iteself by DRM core and drivers. There are at least two such quirks applicable to all drivers: the DPCD register access probe quirk and the 128b/132b DPRX Lane Count Conversion quirk (see 3.5.2.16.3 in the v2.1a DP Standard). The latter quirk applies to panels with specific EDID panel names, support for defining a quirk this way will be added as a follow-up. v2: Reset global_quirks in drm_reset_display_info(). v3: (Jani) - Use one list for both the global and internal quirks. - Drop change for panel name specific quirks. - Add comment about the way quirks should be queried. Cc: Ville Syrjälä Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250605082850.65136-4-imre.deak@intel.com --- drivers/gpu/drm/drm_edid.c | 8 +++++++- include/drm/drm_connector.h | 4 +++- include/drm/drm_edid.h | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 857ae0c47a1c..9cca1e6e4736 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,7 +68,7 @@ static int oui(u8 first, u8 second, u8 third) enum drm_edid_internal_quirk { /* First detailed mode wrong, use largest 60Hz mode */ - EDID_QUIRK_PREFER_LARGE_60, + EDID_QUIRK_PREFER_LARGE_60 = DRM_EDID_QUIRK_NUM, /* Reported 135MHz pixel clock is too high, needs adjustment */ EDID_QUIRK_135_CLOCK_TOO_HIGH, /* Prefer the largest mode at 75 Hz */ @@ -2959,6 +2959,12 @@ static bool drm_edid_has_internal_quirk(struct drm_connector *connector, return connector->display_info.quirks & BIT(quirk); } +bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk) +{ + return connector->display_info.quirks & BIT(quirk); +} +EXPORT_SYMBOL(drm_edid_has_quirk); + #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) #define MODE_REFRESH_DIFF(c,t) (abs((c) - (t))) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index f13d597370a3..da49d520aa3b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -843,7 +843,9 @@ struct drm_display_info { int vics_len; /** - * @quirks: EDID based quirks. Internal to EDID parsing. + * @quirks: EDID based quirks. DRM core and drivers can query the + * @drm_edid_quirk quirks using drm_edid_has_quirk(), the rest of + * the quirks also tracked here are internal to EDID parsing. */ u32 quirks; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index b38409670868..77fd42608e70 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -109,6 +109,10 @@ struct detailed_data_string { #define DRM_EDID_CVT_FLAGS_STANDARD_BLANKING (1 << 3) #define DRM_EDID_CVT_FLAGS_REDUCED_BLANKING (1 << 4) +enum drm_edid_quirk { + DRM_EDID_QUIRK_NUM, +}; + struct detailed_data_monitor_range { u8 min_vfreq; u8 max_vfreq; @@ -476,5 +480,6 @@ void drm_edid_print_product_id(struct drm_printer *p, u32 drm_edid_get_panel_id(const struct drm_edid *drm_edid); bool drm_edid_match(const struct drm_edid *drm_edid, const struct drm_edid_ident *ident); +bool drm_edid_has_quirk(struct drm_connector *connector, enum drm_edid_quirk quirk); #endif /* __DRM_EDID_H__ */ -- cgit v1.2.3 From b87ed522b3643f096ef183ed0ccf2d2b90ddd513 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 9 Jun 2025 15:55:55 +0300 Subject: drm/dp: Add an EDID quirk for the DPCD register access probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reading DPCD registers has side-effects and some of these can cause a problem for instance during link training. Based on this it's better to avoid the probing quirk done before each DPCD register read, limiting this to the monitor which requires it. Add an EDID quirk for this. Leave the quirk enabled by default, allowing it to be disabled after the monitor is detected. v2: Fix lockdep wrt. drm_dp_aux::hw_mutex when calling drm_dp_dpcd_set_probe_quirk() with a dependent lock already held. v3: Add a helper for determining if DPCD probing is needed. (Jani) v4: - s/drm_dp_dpcd_set_probe_quirk/drm_dp_dpcd_set_probe (Jani) - Fix documentation of drm_dp_dpcd_set_probe(). - Add comment at the end of internal quirk entries. Cc: Ville Syrjälä Cc: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Imre Deak Link: https://lore.kernel.org/r/20250609125556.109538-1-imre.deak@intel.com --- drivers/gpu/drm/display/drm_dp_helper.c | 42 +++++++++++++++++++++++---------- drivers/gpu/drm/drm_edid.c | 8 +++++++ include/drm/display/drm_dp_helper.h | 6 +++++ include/drm/drm_edid.h | 3 +++ 4 files changed, 46 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index dc622c78db9d..632358b23b33 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -691,6 +691,34 @@ void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered) } EXPORT_SYMBOL(drm_dp_dpcd_set_powered); +/** + * drm_dp_dpcd_set_probe() - Set whether a probing before DPCD access is done + * @aux: DisplayPort AUX channel + * @enable: Enable the probing if required + */ +void drm_dp_dpcd_set_probe(struct drm_dp_aux *aux, bool enable) +{ + WRITE_ONCE(aux->dpcd_probe_disabled, !enable); +} +EXPORT_SYMBOL(drm_dp_dpcd_set_probe); + +static bool dpcd_access_needs_probe(struct drm_dp_aux *aux) +{ + /* + * HP ZR24w corrupts the first DPCD access after entering power save + * mode. Eg. on a read, the entire buffer will be filled with the same + * byte. Do a throw away read to avoid corrupting anything we care + * about. Afterwards things will work correctly until the monitor + * gets woken up and subsequently re-enters power save mode. + * + * The user pressing any button on the monitor is enough to wake it + * up, so there is no particularly good place to do the workaround. + * We just have to do it before any DPCD access and hope that the + * monitor doesn't power down exactly after the throw away read. + */ + return !aux->is_remote && !READ_ONCE(aux->dpcd_probe_disabled); +} + /** * drm_dp_dpcd_read() - read a series of bytes from the DPCD * @aux: DisplayPort AUX channel (SST or MST) @@ -712,19 +740,7 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, { int ret; - /* - * HP ZR24w corrupts the first DPCD access after entering power save - * mode. Eg. on a read, the entire buffer will be filled with the same - * byte. Do a throw away read to avoid corrupting anything we care - * about. Afterwards things will work correctly until the monitor - * gets woken up and subsequently re-enters power save mode. - * - * The user pressing any button on the monitor is enough to wake it - * up, so there is no particularly good place to do the workaround. - * We just have to do it before any DPCD access and hope that the - * monitor doesn't power down exactly after the throw away read. - */ - if (!aux->is_remote) { + if (dpcd_access_needs_probe(aux)) { ret = drm_dp_dpcd_probe(aux, DP_LANE0_1_STATUS); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9cca1e6e4736..9c8822b337e2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -248,6 +248,14 @@ static const struct edid_quirk { /* OSVR HDK and HDK2 VR Headsets */ EDID_QUIRK('S', 'V', 'R', 0x1019, BIT(EDID_QUIRK_NON_DESKTOP)), EDID_QUIRK('A', 'U', 'O', 0x1111, BIT(EDID_QUIRK_NON_DESKTOP)), + + /* + * @drm_edid_internal_quirk entries end here, following with the + * @drm_edid_quirk entries. + */ + + /* HP ZR24w DP AUX DPCD access requires probing to prevent corruption. */ + EDID_QUIRK('H', 'W', 'P', 0x2869, BIT(DRM_EDID_QUIRK_DP_DPCD_PROBE)), }; /* diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_dp_helper.h index e4ca35143ff9..3e35a68b2b41 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -523,10 +523,16 @@ struct drm_dp_aux { * @no_zero_sized: If the hw can't use zero sized transfers (NVIDIA) */ bool no_zero_sized; + + /** + * @dpcd_probe_disabled: If probing before a DPCD access is disabled. + */ + bool dpcd_probe_disabled; }; int drm_dp_dpcd_probe(struct drm_dp_aux *aux, unsigned int offset); void drm_dp_dpcd_set_powered(struct drm_dp_aux *aux, bool powered); +void drm_dp_dpcd_set_probe(struct drm_dp_aux *aux, bool enable); ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, void *buffer, size_t size); ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 77fd42608e70..3d1aecfec9b2 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -110,6 +110,9 @@ struct detailed_data_string { #define DRM_EDID_CVT_FLAGS_REDUCED_BLANKING (1 << 4) enum drm_edid_quirk { + /* Do a dummy read before DPCD accesses, to prevent corruption. */ + DRM_EDID_QUIRK_DP_DPCD_PROBE, + DRM_EDID_QUIRK_NUM, }; -- cgit v1.2.3