The CRC functions found in drivers/gpu/drm/display/drm_dp_mst_topology.c
may be useful for other non-DRM code that deals with DisplayPort, e.g.
v4l2 drivers for DP receivers. Move these functions to /lib.

Signed-off-by: Paweł Anikiel <panik...@google.com>
---
 drivers/gpu/drm/display/Kconfig               |  1 +
 drivers/gpu/drm/display/drm_dp_mst_topology.c | 76 ++----------------
 include/linux/crc-dp.h                        | 10 +++
 lib/Kconfig                                   |  8 ++
 lib/Makefile                                  |  1 +
 lib/crc-dp.c                                  | 78 +++++++++++++++++++
 6 files changed, 103 insertions(+), 71 deletions(-)
 create mode 100644 include/linux/crc-dp.h
 create mode 100644 lib/crc-dp.c

diff --git a/drivers/gpu/drm/display/Kconfig b/drivers/gpu/drm/display/Kconfig
index c0f56888c328..eda19645201d 100644
--- a/drivers/gpu/drm/display/Kconfig
+++ b/drivers/gpu/drm/display/Kconfig
@@ -14,6 +14,7 @@ config DRM_DISPLAY_HELPER
 config DRM_DISPLAY_DP_HELPER
        bool
        depends on DRM_DISPLAY_HELPER
+       select CRC_DP
        help
          DRM display helpers for DisplayPort.
 
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c 
b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index 03d528209426..54ba98d3bc6f 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -22,6 +22,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/delay.h>
+#include <linux/crc-dp.h>
 #include <linux/errno.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
@@ -195,73 +196,6 @@ drm_dp_mst_rad_to_str(const u8 rad[8], u8 lct, char *out, 
size_t len)
 }
 
 /* sideband msg handling */
-static u8 drm_dp_msg_header_crc4(const uint8_t *data, size_t num_nibbles)
-{
-       u8 bitmask = 0x80;
-       u8 bitshift = 7;
-       u8 array_index = 0;
-       int number_of_bits = num_nibbles * 4;
-       u8 remainder = 0;
-
-       while (number_of_bits != 0) {
-               number_of_bits--;
-               remainder <<= 1;
-               remainder |= (data[array_index] & bitmask) >> bitshift;
-               bitmask >>= 1;
-               bitshift--;
-               if (bitmask == 0) {
-                       bitmask = 0x80;
-                       bitshift = 7;
-                       array_index++;
-               }
-               if ((remainder & 0x10) == 0x10)
-                       remainder ^= 0x13;
-       }
-
-       number_of_bits = 4;
-       while (number_of_bits != 0) {
-               number_of_bits--;
-               remainder <<= 1;
-               if ((remainder & 0x10) != 0)
-                       remainder ^= 0x13;
-       }
-
-       return remainder;
-}
-
-static u8 drm_dp_msg_data_crc4(const uint8_t *data, u8 number_of_bytes)
-{
-       u8 bitmask = 0x80;
-       u8 bitshift = 7;
-       u8 array_index = 0;
-       int number_of_bits = number_of_bytes * 8;
-       u16 remainder = 0;
-
-       while (number_of_bits != 0) {
-               number_of_bits--;
-               remainder <<= 1;
-               remainder |= (data[array_index] & bitmask) >> bitshift;
-               bitmask >>= 1;
-               bitshift--;
-               if (bitmask == 0) {
-                       bitmask = 0x80;
-                       bitshift = 7;
-                       array_index++;
-               }
-               if ((remainder & 0x100) == 0x100)
-                       remainder ^= 0xd5;
-       }
-
-       number_of_bits = 8;
-       while (number_of_bits != 0) {
-               number_of_bits--;
-               remainder <<= 1;
-               if ((remainder & 0x100) != 0)
-                       remainder ^= 0xd5;
-       }
-
-       return remainder & 0xff;
-}
 static inline u8 drm_dp_calc_sb_hdr_size(struct drm_dp_sideband_msg_hdr *hdr)
 {
        u8 size = 3;
@@ -284,7 +218,7 @@ static void drm_dp_encode_sideband_msg_hdr(struct 
drm_dp_sideband_msg_hdr *hdr,
                (hdr->msg_len & 0x3f);
        buf[idx++] = (hdr->somt << 7) | (hdr->eomt << 6) | (hdr->seqno << 4);
 
-       crc4 = drm_dp_msg_header_crc4(buf, (idx * 2) - 1);
+       crc4 = crc_dp_msg_header(buf, (idx * 2) - 1);
        buf[idx - 1] |= (crc4 & 0xf);
 
        *len = idx;
@@ -305,7 +239,7 @@ static bool drm_dp_decode_sideband_msg_hdr(const struct 
drm_dp_mst_topology_mgr
        len += ((buf[0] & 0xf0) >> 4) / 2;
        if (len > buflen)
                return false;
-       crc4 = drm_dp_msg_header_crc4(buf, (len * 2) - 1);
+       crc4 = crc_dp_msg_header(buf, (len * 2) - 1);
 
        if ((crc4 & 0xf) != (buf[len - 1] & 0xf)) {
                drm_dbg_kms(mgr->dev, "crc4 mismatch 0x%x 0x%x\n", crc4, 
buf[len - 1]);
@@ -725,7 +659,7 @@ static void drm_dp_crc_sideband_chunk_req(u8 *msg, u8 len)
 {
        u8 crc4;
 
-       crc4 = drm_dp_msg_data_crc4(msg, len);
+       crc4 = crc_dp_msg_data(msg, len);
        msg[len] = crc4;
 }
 
@@ -782,7 +716,7 @@ static bool drm_dp_sideband_append_payload(struct 
drm_dp_sideband_msg_rx *msg,
 
        if (msg->curchunk_idx >= msg->curchunk_len) {
                /* do CRC */
-               crc4 = drm_dp_msg_data_crc4(msg->chunk, msg->curchunk_len - 1);
+               crc4 = crc_dp_msg_data(msg->chunk, msg->curchunk_len - 1);
                if (crc4 != msg->chunk[msg->curchunk_len - 1])
                        print_hex_dump(KERN_DEBUG, "wrong crc",
                                       DUMP_PREFIX_NONE, 16, 1,
diff --git a/include/linux/crc-dp.h b/include/linux/crc-dp.h
new file mode 100644
index 000000000000..b63435c82b96
--- /dev/null
+++ b/include/linux/crc-dp.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_CRC_DP_H
+#define _LINUX_CRC_DP_H
+
+#include <linux/types.h>
+
+u8 crc_dp_msg_header(const uint8_t *data, size_t num_nibbles);
+u8 crc_dp_msg_data(const uint8_t *data, u8 number_of_bytes);
+
+#endif /* _LINUX_CRC_DP_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index 4557bb8a5256..d2836dacf10d 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -168,6 +168,14 @@ config CRC_ITU_T
          the kernel tree does. Such modules that use library CRC ITU-T V.41
          functions require M here.
 
+config CRC_DP
+       tristate "CRC DisplayPort MST functions"
+       help
+         This option is provided for the case where no in-kernel-tree
+         modules require CRC DisplayPort MST functions, but a module built 
outside
+         the kernel tree does. Such modules that use library CRC DisplayPort 
MST
+         functions require M here.
+
 config CRC32
        tristate "CRC32/CRC32c functions"
        default y
diff --git a/lib/Makefile b/lib/Makefile
index ffc6b2341b45..82edf655036b 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -186,6 +186,7 @@ obj-$(CONFIG_CRC7)  += crc7.o
 obj-$(CONFIG_LIBCRC32C)        += libcrc32c.o
 obj-$(CONFIG_CRC8)     += crc8.o
 obj-$(CONFIG_CRC64_ROCKSOFT) += crc64-rocksoft.o
+obj-$(CONFIG_CRC_DP)   += crc-dp.o
 obj-$(CONFIG_XXHASH)   += xxhash.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
diff --git a/lib/crc-dp.c b/lib/crc-dp.c
new file mode 100644
index 000000000000..95b58bc436d4
--- /dev/null
+++ b/lib/crc-dp.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/crc-dp.h>
+
+/*
+ * Sideband MSG Header CRC
+ * Defined in DisplayPort 1.2 spec, section 2.11.3.1.9
+ */
+u8 crc_dp_msg_header(const uint8_t *data, size_t num_nibbles)
+{
+       u8 bitmask = 0x80;
+       u8 bitshift = 7;
+       u8 array_index = 0;
+       int number_of_bits = num_nibbles * 4;
+       u8 remainder = 0;
+
+       while (number_of_bits != 0) {
+               number_of_bits--;
+               remainder <<= 1;
+               remainder |= (data[array_index] & bitmask) >> bitshift;
+               bitmask >>= 1;
+               bitshift--;
+               if (bitmask == 0) {
+                       bitmask = 0x80;
+                       bitshift = 7;
+                       array_index++;
+               }
+               if ((remainder & 0x10) == 0x10)
+                       remainder ^= 0x13;
+       }
+
+       number_of_bits = 4;
+       while (number_of_bits != 0) {
+               number_of_bits--;
+               remainder <<= 1;
+               if ((remainder & 0x10) != 0)
+                       remainder ^= 0x13;
+       }
+
+       return remainder;
+}
+
+/*
+ * Sideband MSG Data CRC
+ * Defined in DisplayPort 1.2 spec, section 2.11.3.2.2
+ */
+u8 crc_dp_msg_data(const uint8_t *data, u8 number_of_bytes)
+{
+       u8 bitmask = 0x80;
+       u8 bitshift = 7;
+       u8 array_index = 0;
+       int number_of_bits = number_of_bytes * 8;
+       u16 remainder = 0;
+
+       while (number_of_bits != 0) {
+               number_of_bits--;
+               remainder <<= 1;
+               remainder |= (data[array_index] & bitmask) >> bitshift;
+               bitmask >>= 1;
+               bitshift--;
+               if (bitmask == 0) {
+                       bitmask = 0x80;
+                       bitshift = 7;
+                       array_index++;
+               }
+               if ((remainder & 0x100) == 0x100)
+                       remainder ^= 0xd5;
+       }
+
+       number_of_bits = 8;
+       while (number_of_bits != 0) {
+               number_of_bits--;
+               remainder <<= 1;
+               if ((remainder & 0x100) != 0)
+                       remainder ^= 0xd5;
+       }
+
+       return remainder & 0xff;
+}
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog

Reply via email to