summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_displayid.c
diff options
context:
space:
mode:
authorJani Nikula <jani.nikula@intel.com>2021-03-29 16:37:16 +0300
committerJani Nikula <jani.nikula@intel.com>2021-03-31 15:41:35 +0300
commit4cc4f09eaa06178bfa8a5b2c753cefb56e1048c8 (patch)
tree63391ab1cfe560c8c14ca9ab8e64eb55485e8008 /drivers/gpu/drm/drm_displayid.c
parent43d16d847eba1469b5579b6515413b4caa07885c (diff)
downloadlinux-4cc4f09eaa06178bfa8a5b2c753cefb56e1048c8.tar.bz2
drm/displayid: add separate drm_displayid.c
We'll be adding more DisplayID specific functions going forward, so start off by splitting out a few functions to a separate file. We don't bother with exporting the functions; at least for now they should be needed solely within drm.ko. No functional changes. Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/07942d5011891b8e8f77245c78b34f4af97a9315.1617024940.git.jani.nikula@intel.com
Diffstat (limited to 'drivers/gpu/drm/drm_displayid.c')
-rw-r--r--drivers/gpu/drm/drm_displayid.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_displayid.c b/drivers/gpu/drm/drm_displayid.c
new file mode 100644
index 000000000000..908bbe6feb61
--- /dev/null
+++ b/drivers/gpu/drm/drm_displayid.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <drm/drm_displayid.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_print.h>
+
+static int validate_displayid(const u8 *displayid, int length, int idx)
+{
+ int i, dispid_length;
+ u8 csum = 0;
+ const struct displayid_hdr *base;
+
+ base = (const struct displayid_hdr *)&displayid[idx];
+
+ DRM_DEBUG_KMS("base revision 0x%x, length %d, %d %d\n",
+ base->rev, base->bytes, base->prod_id, base->ext_count);
+
+ /* +1 for DispID checksum */
+ dispid_length = sizeof(*base) + base->bytes + 1;
+ if (dispid_length > length - idx)
+ return -EINVAL;
+
+ for (i = 0; i < dispid_length; i++)
+ csum += displayid[idx + i];
+ if (csum) {
+ DRM_NOTE("DisplayID checksum invalid, remainder is %d\n", csum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+const u8 *drm_find_displayid_extension(const struct edid *edid,
+ int *length, int *idx,
+ int *ext_index)
+{
+ const u8 *displayid = drm_find_edid_extension(edid, DISPLAYID_EXT, ext_index);
+ const struct displayid_hdr *base;
+ int ret;
+
+ if (!displayid)
+ return NULL;
+
+ /* EDID extensions block checksum isn't for us */
+ *length = EDID_LENGTH - 1;
+ *idx = 1;
+
+ ret = validate_displayid(displayid, *length, *idx);
+ if (ret)
+ return NULL;
+
+ base = (const struct displayid_hdr *)&displayid[*idx];
+ *length = *idx + sizeof(*base) + base->bytes;
+
+ return displayid;
+}