drm/dp: device identification and quirks
Subsystems (3)
cover drm/dp: device identification and quirks
New version of [1] with DPCD OUI etc. reading moved from i915 to DP helpers, and the quirks based on that. Helps improve the documentation that Daniel longed for.
BR,
Jani.
[1] http://mid.mail-archive.com/[email protected]
Jani Nikula (4):
drm/dp: add helper for reading DP sink/branch device desc from DPCD drm/i915: use drm DP helper to read DPCD desc
drm/dp: start a DPCD based DP sink/branch device quirk database drm/i915: Detect USB-C specific dongles before reducing M and N
drivers/gpu/drm/drm_dp_helper.c | 83 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 3 +- drivers/gpu/drm/i915/intel_display.c | 22 ++++++---- drivers/gpu/drm/i915/intel_dp.c | 45 +++++-------------- drivers/gpu/drm/i915/intel_dp_mst.c | 5 ++- drivers/gpu/drm/i915/intel_drv.h | 5 +-- drivers/gpu/drm/i915/intel_lspcon.c | 2 +- include/drm/drm_dp_helper.h | 51 ++++++++++++++++++++++ 8 files changed, 166 insertions(+), 50 deletions(-)
Signature · 6 lines
2.11.0 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 1/4 drm/dp: add helper for reading DP sink/branch device desc from DPCD
--- drivers/gpu/drm/drm_dp_helper.c | 35 +++++++++++++++++++++++++++++++++++ include/drm/drm_dp_helper.h | 19 +++++++++++++++++++ 2 files changed, 54 insertions(+)
drivers/gpu/drm/drm_dp_helper.c +35 -0
@@ -1208,3 +1208,38 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux)return 0 ; }EXPORT_SYMBOL (drm_dp_stop_crc); + +/** +* drm_dp_read_desc - read sink/branch descriptor from DPCD +* @aux: DisplayPort AUX channel +* @desc: Device decriptor to fill from DPCD +* @is_branch: true for branch devices, false for sink devices +* +* Read DPCD 0x400 (sink) or 0x500 (branch) into @desc. Also debug log the +* identification. +* +* Returns 0 on success or a negative error code on failure. +*/ +int drm_dp_read_desc (struct drm_dp_aux *aux,struct drm_dp_desc *desc, +bool is_branch) +{ +struct drm_dp_dpcd_ident *ident = &desc->ident; +unsigned int offset = is_branch ?DP_BRANCH_OUI :DP_SINK_OUI ; +int ret, dev_id_len; + + ret =drm_dp_dpcd_read (aux, offset, ident,sizeof (*ident)); +if (ret <0 ) +return ret; + + dev_id_len =strnlen (ident->device_id,sizeof (ident->device_id)); + +DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , + is_branch ?"branch" :"sink" , + (int )sizeof (ident->oui), ident->oui, + dev_id_len, ident->device_id, + ident->hw_rev >>4 , ident->hw_rev &0xf , + ident->sw_major_rev, ident->sw_minor_rev); + +return 0 ; +} +EXPORT_SYMBOL (drm_dp_read_desc);
include/drm/drm_dp_helper.h +19 -0
@@ -1079,4 +1079,23 @@ void drm_dp_aux_unregister(struct drm_dp_aux *aux);int drm_dp_start_crc (struct drm_dp_aux *aux,struct drm_crtc *crtc);int drm_dp_stop_crc (struct drm_dp_aux *aux); +struct drm_dp_dpcd_ident { +u8 oui[3 ]; +u8 device_id[6 ]; +u8 hw_rev; +u8 sw_major_rev; +u8 sw_minor_rev; +} __packed; + +/** +* struct drm_dp_desc - DP branch/sink device descriptor +* @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). +*/ +struct drm_dp_desc { +struct drm_dp_dpcd_ident ident; +}; + +int drm_dp_read_desc (struct drm_dp_aux *aux,struct drm_dp_desc *desc, +bool is_branch); +#endif /* _DRM_DP_HELPER_H_ */
Signature · 6 lines
2.11.0 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/4 drm/i915: use drm DP helper to read DPCD desc
In reply to Jani NikulaSwitch to using the common DP helpers instead of using our own.
--- drivers/gpu/drm/i915/intel_dp.c | 37 ++++--------------------------------- drivers/gpu/drm/i915/intel_drv.h | 5 +---- drivers/gpu/drm/i915/intel_lspcon.c | 2 +- 3 files changed, 6 insertions(+), 38 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +4 -33
@@ -1548,37 +1548,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)DRM_DEBUG_KMS ("common rates: %s\n" , str); } -bool -__intel_dp_read_desc (struct intel_dp *intel_dp,struct intel_dp_desc *desc) -{ -u32 base =drm_dp_is_branch (intel_dp->dpcd) ?DP_BRANCH_OUI : -DP_SINK_OUI ; - -return drm_dp_dpcd_read (&intel_dp->aux, base, desc,sizeof (*desc)) == -sizeof (*desc); -} - -bool intel_dp_read_desc (struct intel_dp *intel_dp) -{ -struct intel_dp_desc *desc = &intel_dp->desc; -bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT ] & -DP_OUI_SUPPORT ; -int dev_id_len; - -if (!__intel_dp_read_desc (intel_dp, desc)) -return false; - - dev_id_len =strnlen (desc->device_id,sizeof (desc->device_id)); -DRM_DEBUG_KMS ("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , -drm_dp_is_branch (intel_dp->dpcd) ?"branch" :"sink" , - (int )sizeof (desc->oui), desc->oui, oui_sup ?"" :"(NS)" , - dev_id_len, desc->device_id, - desc->hw_rev >>4 , desc->hw_rev &0xf , - desc->sw_major_rev, desc->sw_minor_rev); - -return true; -} -int intel_dp_max_link_rate (struct intel_dp *intel_dp) {
@@ -3662,7 +3631,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)if (!intel_dp_read_dpcd (intel_dp))return false; -intel_dp_read_desc (intel_dp); +drm_dp_read_desc (&intel_dp->aux, &intel_dp->desc, +drm_dp_is_branch (intel_dp->dpcd));if (intel_dp->dpcd[DP_DPCD_REV ] >=0x11 ) dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
@@ -4677,7 +4647,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)intel_dp_print_rates (intel_dp); -intel_dp_read_desc (intel_dp); +drm_dp_read_desc (&intel_dp->aux, &intel_dp->desc, +drm_dp_is_branch (intel_dp->dpcd));intel_dp_configure_mst (intel_dp);
drivers/gpu/drm/i915/intel_drv.h +1 -4
@@ -996,7 +996,7 @@ struct intel_dp {/* Max rate for the current link */ int max_link_rate;/* sink or branch descriptor */ -struct intel_dp_desc desc; +struct drm_dp_desc desc;struct drm_dp_aux aux;enum intel_display_power_domain aux_power_domain;uint8_t train_set[4 ];
@@ -1571,9 +1571,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) }bool intel_dp_read_dpcd (struct intel_dp *intel_dp); -bool __intel_dp_read_desc (struct intel_dp *intel_dp, -struct intel_dp_desc *desc); -bool intel_dp_read_desc (struct intel_dp *intel_dp);int intel_dp_link_required (int pixel_clock,int bpp);int intel_dp_max_data_rate (int max_link_clock,int max_lanes); bool intel_digital_port_connected(struct drm_i915_private *dev_priv,
drivers/gpu/drm/i915/intel_lspcon.c +1 -1
@@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)return false; } -intel_dp_read_desc (dp); +drm_dp_read_desc (&dp->aux, &dp->desc,drm_dp_is_branch (dp->dpcd));DRM_DEBUG_KMS ("Success: LSPCON init\n" );return true;
Signature · 6 lines
2.11.0 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 2/4] drm/i915: use drm DP helper to read DPCD desc
Quoted 3 lines · Jani Nikula
Switch to using the common DP helpers instead of using our own.
Signed-off-by Jani Nikula <[email protected]>
Forgot to remove struct intel_dp_desc, otherwise lgtm.
Quoted 107 lines
--- drivers/gpu/drm/i915/intel_dp.c | 37 ++++--------------------------------- drivers/gpu/drm/i915/intel_drv.h | 5 +---- drivers/gpu/drm/i915/intel_lspcon.c | 2 +- 3 files changed, 6 insertions(+), 38 deletions(-)drivers/gpu/drm/i915/intel_dp.c +4
-33@@ -1548,37 +1548,6 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)DRM_DEBUG_KMS ("common rates: %s\n" , str); } -bool -__intel_dp_read_desc (struct intel_dp *intel_dp,struct intel_dp_desc *desc) -{ -u32 base =drm_dp_is_branch (intel_dp->dpcd) ?DP_BRANCH_OUI : -DP_SINK_OUI ; - -return drm_dp_dpcd_read (&intel_dp->aux, base, desc,sizeof (*desc)) == -sizeof (*desc); -} - -bool intel_dp_read_desc (struct intel_dp *intel_dp) -{ -struct intel_dp_desc *desc = &intel_dp->desc; -bool oui_sup = intel_dp->dpcd[DP_DOWN_STREAM_PORT_COUNT ] & -DP_OUI_SUPPORT ; -int dev_id_len; - -if (!__intel_dp_read_desc (intel_dp, desc)) -return false; - - dev_id_len =strnlen (desc->device_id,sizeof (desc->device_id)); -DRM_DEBUG_KMS ("DP %s: OUI %*phD%s dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , -drm_dp_is_branch (intel_dp->dpcd) ?"branch" :"sink" , - (int )sizeof (desc->oui), desc->oui, oui_sup ?"" :"(NS)" , - dev_id_len, desc->device_id, - desc->hw_rev >>4 , desc->hw_rev &0xf , - desc->sw_major_rev, desc->sw_minor_rev); - -return true; -} -int intel_dp_max_link_rate (struct intel_dp *intel_dp) {@@ -3662,7 +3631,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)if (!intel_dp_read_dpcd (intel_dp))return false; -intel_dp_read_desc (intel_dp); +drm_dp_read_desc (&intel_dp->aux, &intel_dp->desc, +drm_dp_is_branch (intel_dp->dpcd));if (intel_dp->dpcd[DP_DPCD_REV ] >=0x11 ) dev_priv->no_aux_handshake = intel_dp->dpcd[DP_MAX_DOWNSPREAD] &@@ -4677,7 +4647,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)intel_dp_print_rates (intel_dp); -intel_dp_read_desc (intel_dp); +drm_dp_read_desc (&intel_dp->aux, &intel_dp->desc, +drm_dp_is_branch (intel_dp->dpcd));intel_dp_configure_mst (intel_dp);drivers/gpu/drm/i915/intel_drv.h +1
-4@@ -996,7 +996,7 @@ struct intel_dp {/* Max rate for the current link */ int max_link_rate;/* sink or branch descriptor */ -struct intel_dp_desc desc; +struct drm_dp_desc desc;struct drm_dp_aux aux;enum intel_display_power_domain aux_power_domain;uint8_t train_set[4 ];@@ -1571,9 +1571,6 @@ static inline unsigned int intel_dp_unused_lane_mask(int lane_count) }bool intel_dp_read_dpcd (struct intel_dp *intel_dp); -bool __intel_dp_read_desc (struct intel_dp *intel_dp, -struct intel_dp_desc *desc); -bool intel_dp_read_desc (struct intel_dp *intel_dp);int intel_dp_link_required (int pixel_clock,int bpp);int intel_dp_max_data_rate (int max_link_clock,int max_lanes); bool intel_digital_port_connected(struct drm_i915_private *dev_priv,drivers/gpu/drm/i915/intel_lspcon.c +1
-1@@ -240,7 +240,7 @@ bool lspcon_init(struct intel_digital_port *intel_dig_port)return false; } -intel_dp_read_desc (dp); +drm_dp_read_desc (&dp->aux, &dp->desc,drm_dp_is_branch (dp->dpcd));DRM_DEBUG_KMS ("Success: LSPCON init\n" );return true;Signature · 1 line
2.11.0
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/4 drm/dp: start a DPCD based DP sink/branch device quirk database
In reply to Jani NikulaFace the fact, there are Display Port sink and branch devices out there in the wild that don't follow the Display Port specifications, or they have bugs, or just otherwise require special treatment. Start a common quirk database the drivers can query based on the DP device identification. At least for now, we leave the workarounds for the drivers to implement as they see fit.
For starters, add a branch device that can't handle full 24-bit main link M and N attributes properly. Naturally, the workaround of reducing main link attributes for all devices ended up in regressions for other devices. So here we are.
v2: Rebase on DRM DP desc read helpers
--- drivers/gpu/drm/drm_dp_helper.c | 52 +++++++++++++++++++++++++++++++++++++++-- include/drm/drm_dp_helper.h | 32 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-)
drivers/gpu/drm/drm_dp_helper.c +50 -2
@@ -1209,6 +1209,51 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux) }EXPORT_SYMBOL (drm_dp_stop_crc); +struct dpcd_quirk { +u8 oui[3 ]; +bool is_branch; +u32 quirks; +}; + +#define OUI (first, second, third) { (first), (second), (third) } + +static const struct dpcd_quirk dpcd_quirk_list[] = { +/* Analogix 7737 needs reduced M and N at HBR2 link rates */ + {OUI (0x00 ,0x22 ,0xb9 ), true,BIT (DP_DPCD_QUIRK_LIMITED_M_N ) }, +}; + +#undef OUI + +/* +* Get a bit mask of DPCD quirks for the sink/branch device identified by +* ident. The quirk data is shared but it's up to the drivers to act on the +* data. +* +* For now, only the OUI (first three bytes) is used, but this may be extended +* to device identification string and hardware/firmware revisions later. +*/ +static u32 +drm_dp_get_quirks (const struct drm_dp_dpcd_ident *ident,bool is_branch) +{ +const struct dpcd_quirk *quirk; +u32 quirks =0 ; +int i; + +for (i =0 ; i <ARRAY_SIZE (dpcd_quirk_list); i++) { + quirk = &dpcd_quirk_list[i]; + +if (quirk->is_branch != is_branch) +continue ; + +if (memcmp (quirk->oui, ident->oui,sizeof (ident->oui) !=0 )) +continue ; + + quirks |= quirk->quirks; + } + +return quirks; +} +/** * drm_dp_read_desc - read sink/branch descriptor from DPCD * @aux: DisplayPort AUX channel
@@ -1231,14 +1276,17 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,if (ret <0 )return ret; + desc->quirks =drm_dp_get_quirks (ident, is_branch); + dev_id_len =strnlen (ident->device_id,sizeof (ident->device_id)); -DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , +DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n" , is_branch ?"branch" :"sink" , (int )sizeof (ident->oui), ident->oui, dev_id_len, ident->device_id, ident->hw_rev >>4 , ident->hw_rev &0xf , - ident->sw_major_rev, ident->sw_minor_rev); + ident->sw_major_rev, ident->sw_minor_rev, + desc->quirks);return 0 ; }
include/drm/drm_dp_helper.h +32 -0
@@ -1090,12 +1090,44 @@ struct drm_dp_dpcd_ident {/** * struct drm_dp_desc - DP branch/sink device descriptor * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). +* @quirks: Quirks; use drm_dp_has_quirk() to query for the quirks. */ struct drm_dp_desc {struct drm_dp_dpcd_ident ident; +u32 quirks; };int drm_dp_read_desc (struct drm_dp_aux *aux,struct drm_dp_desc *desc,bool is_branch); +/** +* enum drm_dp_quirk - Display Port sink/branch device specific quirks +* +* Display Port sink and branch devices in the wild have a variety of bugs, try +* to collect them here. The quirks are shared, but it's up to the drivers to +* implement workarounds for them. +*/ +enum drm_dp_quirk { +/** +* @DP_DPCD_QUIRK_LIMITED_M_N: +* +* The device requires main link attributes Mdiv and Ndiv to be limited +* to 16 bits. +*/ +DP_DPCD_QUIRK_LIMITED_M_N , +}; + +/** +* drm_dp_has_quirk() - does the DP device have a specific quirk +* @desc: Device decriptor filled by drm_dp_read_desc() +* @quirk: Quirk to query for +* +* Return true if DP device identified by @desc has @quirk. +*/ +static inline bool +drm_dp_has_quirk (const struct drm_dp_desc *desc,enum drm_dp_quirk quirk) +{ +return desc->quirks &BIT (quirk); +} +#endif /* _DRM_DP_HELPER_H_ */
Signature · 6 lines
2.11.0 _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/4] drm/dp: start a DPCD based DP sink/branch device quirk database
Quoted 61 lines · Jani Nikula
Face the fact, there are Display Port sink and branch devices out there in the wild that don't follow the Display Port specifications, or they have bugs, or just otherwise require special treatment. Start a common quirk database the drivers can query based on the DP device identification. At least for now, we leave the workarounds for the drivers to implement as they see fit.
For starters, add a branch device that can't handle full 24-bit main link M and N attributes properly. Naturally, the workaround of reducing main link attributes for all devices ended up in regressions for other devices. So here we are.
v2: Rebase on DRM DP desc read helpers
Cc Ville Syrjälä <[email protected]>Cc Dhinakaran Pandiyan <[email protected]>Cc Clint Taylor <[email protected]>Cc Adam Jackson <[email protected]>Cc Harry Wentland <[email protected]>Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/drm_dp_helper.c | 52 +++++++++++++++++++++++++++++++++++++++-- include/drm/drm_dp_helper.h | 32 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-)drivers/gpu/drm/drm_dp_helper.c +28
-0@@ -1209,6 +1209,51 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux) }EXPORT_SYMBOL (drm_dp_stop_crc); +struct dpcd_quirk { +u8 oui[3 ]; +bool is_branch; +u32 quirks; +}; + +#define OUI (first, second, third) { (first), (second), (third) } + +static const struct dpcd_quirk dpcd_quirk_list[] = { +/* Analogix 7737 needs reduced M and N at HBR2 link rates */ + {OUI (0x00 ,0x22 ,0xb9 ), true,BIT (DP_DPCD_QUIRK_LIMITED_M_N ) }, +}; + +#undef OUI + +/* +* Get a bit mask of DPCD quirks for the sink/branch device identified by +* ident. The quirk data is shared but it's up to the drivers to act on the +* data. +* +* For now, only the OUI (first three bytes) is used, but this may be extended +* to device identification string and hardware/firmware revisions later. +*/ +static u32 +drm_dp_get_quirks (const struct drm_dp_dpcd_ident *ident,bool is_branch) +{ +const struct dpcd_quirk *quirk; +u32 quirks =0 ;
drivers/gpu/drm/drm_dp_helper.c int drm_dp_stop_crc(struct drm_dp_aux *aux) · line 1249
Quoted 10 lines
drivers/gpu/drm/drm_dp_helper.c +10
-0+int i; + +for (i =0 ; i <ARRAY_SIZE (dpcd_quirk_list); i++) { + quirk = &dpcd_quirk_list[i]; + +if (quirk->is_branch != is_branch) +continue ; + +if (memcmp (quirk->oui, ident->oui,sizeof (ident->oui) !=0 )) +continue ;
Oops, All branch devices appear to have the quirk applied. The memcmp should be closed before the !=0
if (memcmp(quirk->oui, ident->oui, sizeof(ident->oui)) != 0)
[ 659.496861] [drm:drm_dp_read_desc] DP branch: OUI 00-1c-f8 dev-ID 175IB0 HW-rev 1.0 SW-rev 7.32 quirks 0x0001 [ 659.549017] [drm:drm_dp_read_desc] DP branch: OUI 00-22-b9 dev-ID 7737 HW-rev 10.12 SW-rev 6.4 quirks 0x0001 [ 659.630449] [drm:drm_dp_read_desc] DP sink: OUI ee-ff-c0 dev-ID \001 HW-rev 0.0 SW-rev 0.0 quirks 0x0000
This was actually good to find out that LSPCON didn't like the reduced M and N from the quirk at HBR2.
-Clint
Quoted 69 lines
drivers/gpu/drm/drm_dp_helper.c +12
-2+ + quirks |= quirk->quirks; + } + +return quirks; +} +/** * drm_dp_read_desc - read sink/branch descriptor from DPCD * @aux: DisplayPort AUX channel @@ -1231,14 +1276,17 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,if (ret <0 )return ret; + desc->quirks =drm_dp_get_quirks (ident, is_branch); + dev_id_len =strnlen (ident->device_id,sizeof (ident->device_id)); -DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , +DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n" , is_branch ?"branch" :"sink" , (int )sizeof (ident->oui), ident->oui, dev_id_len, ident->device_id, ident->hw_rev >>4 , ident->hw_rev &0xf , - ident->sw_major_rev, ident->sw_minor_rev); + ident->sw_major_rev, ident->sw_minor_rev, + desc->quirks);return 0 ; }include/drm/drm_dp_helper.h +23
-0@@ -1090,12 +1090,44 @@ struct drm_dp_dpcd_ident {/** * struct drm_dp_desc - DP branch/sink device descriptor * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). +* @quirks: Quirks; use drm_dp_has_quirk() to query for the quirks. */ struct drm_dp_desc {struct drm_dp_dpcd_ident ident; +u32 quirks; };int drm_dp_read_desc (struct drm_dp_aux *aux,struct drm_dp_desc *desc,bool is_branch); +/** +* enum drm_dp_quirk - Display Port sink/branch device specific quirks +* +* Display Port sink and branch devices in the wild have a variety of bugs, try +* to collect them here. The quirks are shared, but it's up to the drivers to +* implement workarounds for them. +*/ +enum drm_dp_quirk { +/** +* @DP_DPCD_QUIRK_LIMITED_M_N: +* +* The device requires main link attributes Mdiv and Ndiv to be limited +* to 16 bits. +*/ +DP_DPCD_QUIRK_LIMITED_M_N , +}; + +/** +* drm_dp_has_quirk() - does the DP device have a specific quirk +* @desc: Device decriptor filled by drm_dp_read_desc() +* @quirk: Quirk to query for
include/drm/drm_dp_helper.h struct drm_dp_dpcd_ident { · line 1133
Quoted 10 lines
include/drm/drm_dp_helper.h +9
-0+* +* Return true if DP device identified by @desc has @quirk. +*/ +static inline bool +drm_dp_has_quirk (const struct drm_dp_desc *desc,enum drm_dp_quirk quirk) +{ +return desc->quirks &BIT (quirk); +} +#endif /* _DRM_DP_HELPER_H_ */
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 3/4] drm/dp: start a DPCD based DP sink/branch device quirk database
Quoted 67 lines · Clint Taylor
Quoted 66 lines · Jani Nikula
Face the fact, there are Display Port sink and branch devices out there in the wild that don't follow the Display Port specifications, or they have bugs, or just otherwise require special treatment. Start a common quirk database the drivers can query based on the DP device identification. At least for now, we leave the workarounds for the drivers to implement as they see fit.
For starters, add a branch device that can't handle full 24-bit main link M and N attributes properly. Naturally, the workaround of reducing main link attributes for all devices ended up in regressions for other devices. So here we are.
v2: Rebase on DRM DP desc read helpers
Cc Ville Syrjälä <[email protected]>Cc Dhinakaran Pandiyan <[email protected]>Cc Clint Taylor <[email protected]>Cc Adam Jackson <[email protected]>Cc Harry Wentland <[email protected]>Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/drm_dp_helper.c | 52 +++++++++++++++++++++++++++++++++++++++-- include/drm/drm_dp_helper.h | 32 +++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-)drivers/gpu/drm/drm_dp_helper.c +33
-0@@ -1209,6 +1209,51 @@ int drm_dp_stop_crc(struct drm_dp_aux *aux) }EXPORT_SYMBOL (drm_dp_stop_crc); +struct dpcd_quirk { +u8 oui[3 ]; +bool is_branch; +u32 quirks; +}; + +#define OUI (first, second, third) { (first), (second), (third) } + +static const struct dpcd_quirk dpcd_quirk_list[] = { +/* Analogix 7737 needs reduced M and N at HBR2 link rates */ + {OUI (0x00 ,0x22 ,0xb9 ), true,BIT (DP_DPCD_QUIRK_LIMITED_M_N ) }, +}; + +#undef OUI + +/* +* Get a bit mask of DPCD quirks for the sink/branch device identified by +* ident. The quirk data is shared but it's up to the drivers to act on the +* data. +* +* For now, only the OUI (first three bytes) is used, but this may be extended +* to device identification string and hardware/firmware revisions later. +*/ +static u32 +drm_dp_get_quirks (const struct drm_dp_dpcd_ident *ident,bool is_branch) +{ +const struct dpcd_quirk *quirk; +u32 quirks =0 ; +int i; + +for (i =0 ; i <ARRAY_SIZE (dpcd_quirk_list); i++) { + quirk = &dpcd_quirk_list[i]; +
Quoted 8 lines
drivers/gpu/drm/drm_dp_helper.c int drm_dp_stop_crc(struct drm_dp_aux *aux) · line 1249
Quoted 5 lines
drivers/gpu/drm/drm_dp_helper.c +5
-0+if (quirk->is_branch != is_branch) +continue ; + +if (memcmp (quirk->oui, ident->oui,sizeof (ident->oui) !=0 )) +continue ;Oops, All branch devices appear to have the quirk applied. The memcmp should be closed before the !=0
Now that's embarrassing. Thanks for catching this.
BR,
Jani.
Quoted 96 lines
if (
memcmp(quirk->oui, ident->oui, sizeof(ident->oui))!= 0)[ 659.496861] [drm:drm_dp_read_desc] DP branch: OUI 00-1c-f8 dev-ID 175IB0 HW-rev 1.0 SW-rev 7.32 quirks 0x0001 [ 659.549017] [drm:drm_dp_read_desc] DP branch: OUI 00-22-b9 dev-ID 7737 HW-rev 10.12 SW-rev 6.4 quirks 0x0001 [ 659.630449] [drm:drm_dp_read_desc] DP sink: OUI ee-ff-c0 dev-ID \001HW-rev 0.0 SW-rev 0.0 quirks
0x0000This was actually good to find out that LSPCON didn't like the reduced M and N from the quirk at HBR2.
-Clint
Quoted 79 lines
drivers/gpu/drm/drm_dp_helper.c +12
-2+ + quirks |= quirk->quirks; + } + +return quirks; +} +/** * drm_dp_read_desc - read sink/branch descriptor from DPCD * @aux: DisplayPort AUX channel @@ -1231,14 +1276,17 @@ int drm_dp_read_desc(struct drm_dp_aux *aux, struct drm_dp_desc *desc,if (ret <0 )return ret; + desc->quirks =drm_dp_get_quirks (ident, is_branch); + dev_id_len =strnlen (ident->device_id,sizeof (ident->device_id)); -DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d\n" , +DRM_DEBUG_KMS ("DP %s: OUI %*phD dev-ID %*pE HW-rev %d.%d SW-rev %d.%d quirks 0x%04x\n" , is_branch ?"branch" :"sink" , (int )sizeof (ident->oui), ident->oui, dev_id_len, ident->device_id, ident->hw_rev >>4 , ident->hw_rev &0xf , - ident->sw_major_rev, ident->sw_minor_rev); + ident->sw_major_rev, ident->sw_minor_rev, + desc->quirks);return 0 ; }include/drm/drm_dp_helper.h +32
-0@@ -1090,12 +1090,44 @@ struct drm_dp_dpcd_ident {/** * struct drm_dp_desc - DP branch/sink device descriptor * @ident: DP device identification from DPCD 0x400 (sink) or 0x500 (branch). +* @quirks: Quirks; use drm_dp_has_quirk() to query for the quirks. */ struct drm_dp_desc {struct drm_dp_dpcd_ident ident; +u32 quirks; };int drm_dp_read_desc (struct drm_dp_aux *aux,struct drm_dp_desc *desc,bool is_branch); +/** +* enum drm_dp_quirk - Display Port sink/branch device specific quirks +* +* Display Port sink and branch devices in the wild have a variety of bugs, try +* to collect them here. The quirks are shared, but it's up to the drivers to +* implement workarounds for them. +*/ +enum drm_dp_quirk { +/** +* @DP_DPCD_QUIRK_LIMITED_M_N: +* +* The device requires main link attributes Mdiv and Ndiv to be limited +* to 16 bits. +*/ +DP_DPCD_QUIRK_LIMITED_M_N , +}; + +/** +* drm_dp_has_quirk() - does the DP device have a specific quirk +* @desc: Device decriptor filled by drm_dp_read_desc() +* @quirk: Quirk to query for +* +* Return true if DP device identified by @desc has @quirk. +*/ +static inline bool +drm_dp_has_quirk (const struct drm_dp_desc *desc,enum drm_dp_quirk quirk) +{ +return desc->quirks &BIT (quirk); +} +#endif /* _DRM_DP_HELPER_H_ */
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 4/4 drm/i915: Detect USB-C specific dongles before reducing M and N
In reply to Jani NikulaThe Analogix 7737 DP to HDMI converter requires reduced M and N values when to operate correctly at HBR2. Detect this IC by its OUI value of 0x0022B9 via the DPCD quirk list.
v2 by Jani: Rebased on the DP quirk database
v3 by Jani: Rebased on the reworked DP quirk database
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93578
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100755
--- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++-------- drivers/gpu/drm/i915/intel_dp.c | 8 ++++++-- drivers/gpu/drm/i915/intel_dp_mst.c | 5 ++++- 4 files changed, 26 insertions(+), 12 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +2 -1
@@ -563,7 +563,8 @@ struct intel_link_m_n {void intel_link_compute_m_n (int bpp,int nlanes,int pixel_clock,int link_clock, -struct intel_link_m_n *m_n); +struct intel_link_m_n *m_n, +bool reduce_m_n);/* Interface history: *
drivers/gpu/drm/i915/intel_display.c +14 -8
@@ -6116,7 +6116,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, pipe_config->fdi_lanes = lane;intel_link_compute_m_n (pipe_config->pipe_bpp, lane, fdi_dotclock, - link_bw, &pipe_config->fdi_m_n); + link_bw, &pipe_config->fdi_m_n, false); ret =ironlake_check_fdi_lanes (dev, intel_crtc->pipe, pipe_config);if (ret == -EINVAL && pipe_config->pipe_bpp >6 *3 ) {
@@ -6292,7 +6292,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) }static void compute_m_n (unsigned int m,unsigned int n, -uint32_t *ret_m,uint32_t *ret_n) +uint32_t *ret_m,uint32_t *ret_n, +bool reduce_m_n) {/* * Reduce M/N as much as possible without loss in precision. Several DP
@@ -6300,9 +6301,11 @@ static void compute_m_n(unsigned int m, unsigned int n,* values. The passed in values are more likely to have the least * significant bits zero than M after rounding below, so do this first. */ -while ((m &1 ) ==0 && (n &1 ) ==0 ) { - m >>=1 ; - n >>=1 ; +if (reduce_m_n) { +while ((m &1 ) ==0 && (n &1 ) ==0 ) { + m >>=1 ; + n >>=1 ; + } } *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);
@@ -6313,16 +6316,19 @@ static void compute_m_n(unsigned int m, unsigned int n,void intel_link_compute_m_n (int bits_per_pixel,int nlanes,int pixel_clock,int link_clock, -struct intel_link_m_n *m_n) +struct intel_link_m_n *m_n, +bool reduce_m_n) { m_n->tu =64 ;compute_m_n (bits_per_pixel * pixel_clock, link_clock * nlanes *8 , - &m_n->gmch_m, &m_n->gmch_n); + &m_n->gmch_m, &m_n->gmch_n, + reduce_m_n);compute_m_n (pixel_clock, link_clock, - &m_n->link_m, &m_n->link_n); + &m_n->link_m, &m_n->link_n, + reduce_m_n); }static inline bool intel_panel_use_ssc (struct drm_i915_private *dev_priv)
drivers/gpu/drm/i915/intel_dp.c +6 -2
@@ -1627,6 +1627,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,int link_avail, link_clock;int common_len;uint8_t link_bw, rate_select; +bool reduce_m_n =drm_dp_has_quirk (&intel_dp->desc, +DP_DPCD_QUIRK_LIMITED_M_N ); common_len =intel_dp_common_len_rate_limit (intel_dp, intel_dp->max_link_rate);
@@ -1759,7 +1761,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n);if (intel_connector->panel.downclock_mode !=NULL && dev_priv->drrs.type ==SEAMLESS_DRRS_SUPPORT ) {
@@ -1767,7 +1770,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, intel_connector->panel.downclock_mode->clock, pipe_config->port_clock, - &pipe_config->dp_m2_n2); + &pipe_config->dp_m2_n2, + reduce_m_n); }/*
drivers/gpu/drm/i915/intel_dp_mst.c +4 -1
@@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,int lane_count, slots;const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;int mst_pbn; +bool reduce_m_n =drm_dp_has_quirk (&intel_dp->desc, +DP_DPCD_QUIRK_LIMITED_M_N ); pipe_config->has_pch_encoder = false; bpp =24 ;
@@ -79,7 +81,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n); pipe_config->dp_m_n.tu = slots;
Signature · 6 lines
2.11.0 _______________________________________________ Intel-gfx mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 4/4] drm/i915: Detect USB-C specific dongles before reducing M and N
Quoted 3 lines · Jani Nikula
The Analogix 7737 DP to HDMI converter requires reduced M and N values when to operate correctly at HBR2. Detect this IC by its OUI value of
0x0022B9via the DPCD quirk list.
Commit message is a bit confusing since this sounds like you're fixing things for the offending analogix bridge, but what this does is fix things for other broken chips. That part is only clear when looking at the Fixes:
commit and bug reports.
With the commit message fixed up to make this clear:
Also patches 1&3 look good now, also Reviewed-by: Daniel Vetter <[email protected]> for those.
Cheers, Daniel
Quoted 154 lines
v2 by Jani: Rebased on the DP quirk database
v3 by Jani: Rebased on the reworked DP quirk database
Fixes 9a86cda07af2 ("drm/i915/dp: reduce link M/N parameters")Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=93578
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=100755Cc Jani Nikula <[email protected]>Cc Dhinakaran Pandiyan <[email protected]>Cc Ville Syrjälä <[email protected]>Signed-off-by Clint Taylor <[email protected]>Signed-off-by Jani Nikula <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_display.c | 22 ++++++++++++++-------- drivers/gpu/drm/i915/intel_dp.c | 8 ++++++-- drivers/gpu/drm/i915/intel_dp_mst.c | 5 ++++- 4 files changed, 26 insertions(+), 12 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-1@@ -563,7 +563,8 @@ struct intel_link_m_n {void intel_link_compute_m_n (int bpp,int nlanes,int pixel_clock,int link_clock, -struct intel_link_m_n *m_n); +struct intel_link_m_n *m_n, +bool reduce_m_n);/* Interface history: * drivers/gpu/drm/i915/intel_display.c +14
-8@@ -6116,7 +6116,7 @@ static int ironlake_fdi_compute_config(struct intel_crtc *intel_crtc, pipe_config->fdi_lanes = lane;intel_link_compute_m_n (pipe_config->pipe_bpp, lane, fdi_dotclock, - link_bw, &pipe_config->fdi_m_n); + link_bw, &pipe_config->fdi_m_n, false); ret =ironlake_check_fdi_lanes (dev, intel_crtc->pipe, pipe_config);if (ret == -EINVAL && pipe_config->pipe_bpp >6 *3 ) {@@ -6292,7 +6292,8 @@ intel_reduce_m_n_ratio(uint32_t *num, uint32_t *den) }static void compute_m_n (unsigned int m,unsigned int n, -uint32_t *ret_m,uint32_t *ret_n) +uint32_t *ret_m,uint32_t *ret_n, +bool reduce_m_n) {/* * Reduce M/N as much as possible without loss in precision. Several DP @@ -6300,9 +6301,11 @@ static void compute_m_n(unsigned int m, unsigned int n,* values. The passed in values are more likely to have the least * significant bits zero than M after rounding below, so do this first. */ -while ((m &1 ) ==0 && (n &1 ) ==0 ) { - m >>=1 ; - n >>=1 ; +if (reduce_m_n) { +while ((m &1 ) ==0 && (n &1 ) ==0 ) { + m >>=1 ; + n >>=1 ; + } } *ret_n = min_t(unsigned int, roundup_pow_of_two(n), DATA_LINK_N_MAX);@@ -6313,16 +6316,19 @@ static void compute_m_n(unsigned int m, unsigned int n,void intel_link_compute_m_n (int bits_per_pixel,int nlanes,int pixel_clock,int link_clock, -struct intel_link_m_n *m_n) +struct intel_link_m_n *m_n, +bool reduce_m_n) { m_n->tu =64 ;compute_m_n (bits_per_pixel * pixel_clock, link_clock * nlanes *8 , - &m_n->gmch_m, &m_n->gmch_n); + &m_n->gmch_m, &m_n->gmch_n, + reduce_m_n);compute_m_n (pixel_clock, link_clock, - &m_n->link_m, &m_n->link_n); + &m_n->link_m, &m_n->link_n, + reduce_m_n); }static inline bool intel_panel_use_ssc (struct drm_i915_private *dev_priv)drivers/gpu/drm/i915/intel_dp.c +6
-2@@ -1627,6 +1627,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,int link_avail, link_clock;int common_len;uint8_t link_bw, rate_select; +bool reduce_m_n =drm_dp_has_quirk (&intel_dp->desc, +DP_DPCD_QUIRK_LIMITED_M_N ); common_len =intel_dp_common_len_rate_limit (intel_dp, intel_dp->max_link_rate);@@ -1759,7 +1761,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n);if (intel_connector->panel.downclock_mode !=NULL && dev_priv->drrs.type ==SEAMLESS_DRRS_SUPPORT ) {@@ -1767,7 +1770,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, intel_connector->panel.downclock_mode->clock, pipe_config->port_clock, - &pipe_config->dp_m2_n2); + &pipe_config->dp_m2_n2, + reduce_m_n); }/* drivers/gpu/drm/i915/intel_dp_mst.c +4
-1@@ -44,6 +44,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,int lane_count, slots;const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;int mst_pbn; +bool reduce_m_n =drm_dp_has_quirk (&intel_dp->desc, +DP_DPCD_QUIRK_LIMITED_M_N ); pipe_config->has_pch_encoder = false; bpp =24 ;@@ -79,7 +81,8 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,intel_link_compute_m_n (bpp, lane_count, adjusted_mode->crtc_clock, pipe_config->port_clock, - &pipe_config->dp_m_n); + &pipe_config->dp_m_n, + reduce_m_n); pipe_config->dp_m_n.tu = slots;Signature · 1 line
2.11.0
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dri-devel
Patchwork
CI✓ Fi.CI.BAT: success for drm/dp: device identification and quirks
In reply to Jani Nikula== Series Details ==
== Series Details ==
Series: drm/dp: device identification and quirks
URL : https://patchwork.freedesktop.org/series/24566/
State : success
== Summary ==
Series 24566v1 drm/dp: device identification and quirks
https://patchwork.freedesktop.org/api/1.0/series/24566/revisions/1/mbox/
Test gem_exec_suspend:
Subgroup basic-s3:
dmesg-warn -> PASS (fi-kbl-7500u) fdo#101022 +3
Subgroup basic-s4-devices:
dmesg-warn -> PASS (fi-kbl-7500u) fdo#100904fdo#101022 https://bugs.freedesktop.org/show_bug.cgi?id=101022
fdo#100904 https://bugs.freedesktop.org/show_bug.cgi?id=100904
fi-bdw-5557u total:278 pass:267 dwarn:0 dfail:0 fail:0 skip:11 time:445s fi-bsw-n3050 total:278 pass:242 dwarn:0 dfail:0 fail:0 skip:36 time:581s fi-bxt-j4205 total:278 pass:259 dwarn:0 dfail:0 fail:0 skip:19 time:512s fi-byt-j1900 total:278 pass:254 dwarn:0 dfail:0 fail:0 skip:24 time:496s fi-byt-n2820 total:278 pass:250 dwarn:0 dfail:0 fail:0 skip:28 time:491s fi-hsw-4770 total:278 pass:262 dwarn:0 dfail:0 fail:0 skip:16 time:417s fi-hsw-4770r total:278 pass:262 dwarn:0 dfail:0 fail:0 skip:16 time:409s fi-ilk-650 total:278 pass:228 dwarn:0 dfail:0 fail:0 skip:50 time:424s fi-ivb-3520m total:278 pass:260 dwarn:0 dfail:0 fail:0 skip:18 time:500s fi-ivb-3770 total:278 pass:260 dwarn:0 dfail:0 fail:0 skip:18 time:461s fi-kbl-7500u total:278 pass:260 dwarn:0 dfail:0 fail:0 skip:18 time:455s fi-skl-6260u total:278 pass:268 dwarn:0 dfail:0 fail:0 skip:10 time:452s fi-skl-6700hq total:278 pass:261 dwarn:0 dfail:0 fail:0 skip:17 time:583s fi-skl-6700k total:278 pass:256 dwarn:4 dfail:0 fail:0 skip:18 time:464s fi-skl-6770hq total:278 pass:268 dwarn:0 dfail:0 fail:0 skip:10 time:502s fi-snb-2520m total:278 pass:250 dwarn:0 dfail:0 fail:0 skip:28 time:537s fi-snb-2600 total:278 pass:249 dwarn:0 dfail:0 fail:0 skip:29 time:407s
eb3549d312620118dec3a69200894ac8a8fff358 drm-tip: 2017y-05m-17d-13h-53m-40s UTC integration manifest faca378 drm/i915: Detect USB-C specific dongles before reducing M and N
0ca6878 drm/dp: start a DPCD based DP sink/branch device quirk database
48ad1d4 drm/i915: use drm DP helper to read DPCD desc
4a2f44b drm/dp: add helper for reading DP sink/branch device desc from DPCD
== Logs ==
For more details see: https://intel-gfx-ci.01.org/CI/Patchwork_4726/
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx