summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2017-05-18 13:10:24 +0200
committerJani Nikula <jani.nikula@intel.com>2017-05-29 12:43:26 +0200
commit76fa998acd86b6b40d0217e12af39c2406bdcd2b (patch)
treed9205f4e5aa77765937c651fa488c05f942a5ea7 /drivers
parentdrm/i915: use drm DP helper to read DPCD desc (diff)
downloadlinux-76fa998acd86b6b40d0217e12af39c2406bdcd2b.tar.xz
linux-76fa998acd86b6b40d0217e12af39c2406bdcd2b.zip
drm/dp: start a DPCD based DP sink/branch device quirk database
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 Mdiv and Ndiv main link 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 v3: Fix the OUI memcmp blunder (Clint) Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com> Cc: Clint Taylor <clinton.a.taylor@intel.com> Cc: Adam Jackson <ajax@redhat.com> Cc: Harry Wentland <harry.wentland@amd.com> Tested-by: Clinton Taylor <clinton.a.taylor@intel.com> Reviewed-by: Clinton Taylor <clinton.a.taylor@intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> # v2 Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/91ec198dd95258dbf3bee2f6be739e0da73b4fdd.1495105635.git.jani.nikula@intel.com
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/drm_dp_helper.c52
1 files changed, 50 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index 52e0ca9a5bb1..213fb837e1c4 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -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;
}