summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2022-09-06 10:56:03 +0200
committerDaniel Vetter <daniel.vetter@ffwll.ch>2022-09-06 10:56:04 +0200
commit8284bae723f025cb6a8431566757a3854a3c53eb (patch)
tree91c86c11413d12add21973c46b0a58f72ad103e0 /drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
parent2c2d7a67defa198a8b8148dbaddc9e5554efebc8 (diff)
parent8869fa666a9e6782c3c896c1fa57d65adca23249 (diff)
Merge tag 'drm-misc-next-2022-08-20-1' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v6.1: UAPI Changes: Cross-subsystem Changes: - DMA-buf: documentation updates. - Assorted small fixes to vga16fb - Fix fbdev drivers to use the aperture helpers. - Make removal of conflicting drivers work correctly without fbdev enabled. Core Changes: - bridge, scheduler, dp-mst: Assorted small fixes. - Add more format helpers to fourcc, and use it to replace the cpp usage. - Add DRM_FORMAT_Cxx, DRM_FORMAT_Rxx (single channel), and DRM_FORMAT_Dxx ("darkness", inverted single channel) - Add packed AYUV8888 and XYUV8888 formats. - Assorted documentation updates. - Rename ttm_bo_init to ttm_bo_init_validate. - Allow TTM bo's to exist without backing store. - Convert drm selftests to kunit. - Add managed init functions for (panel) bridge, crtc, encoder and connector. - Fix endianness handling in various format conversion helpers. - Make tests pass on big-endian platforms, and add test for rgb888 -> rgb565 - Move DRM_PLANE_HELPER_NO_SCALING to atomic helpers and rename, so drm_plane_helper is no longer needed in most drivers. - Use idr_init_base instead of idr_init. - Rename FB and GEM CMA helpers to DMA helpers. - Rework XRGB8888 related conversion helpers, and add drm_fb_blit() that takes a iosys_map. Make drm_fb_memcpy take an iosys_map too. - Move edid luminance calculation to core, and use it in i915. Driver Changes: - bridge/{adv7511,ti-sn65dsi86,parade-ps8640}, panel/{simple,nt35510,tc358767}, nouveau, sun4i, mipi-dsi, mgag200, bochs, arm, komeda, vmwgfx, pl111: Assorted small fixes and doc updates. - vc4: Rework hdmi power up, and depend on PM. - panel/simple: Add Samsung LTL101AL01. - ingenic: Add JZ4760(B) support, avoid a modeset when sharpness property is unchanged, and use the new PM ops. - Revert some amdgpu commits that cause garbaged graphics when starting X, and reapply them with the real problem fixed. - Completely rework vc4 init to use managed helpers. - Rename via_drv to via_dri1, and move all stuff there only used by the dri1 implementation in preperation for atomic modeset. - Use regmap bulk write in ssd130x. - Power sequence and clock updates to it6505. - Split panel-sitrox-st7701 init sequence and rework mode programming code. - virtio: Improve error and edge conditions handling, and convert to use managed helpers. - Add Samsung LTL101AL01, B120XAN01.0, R140NWF5 RH, DMT028VGHMCMI-1A T, panels. - Add generic fbdev support to komeda. - Split mgag200 modeset handling to make it more model-specific. - Convert simpledrm to use atomic helpers. - Improve udl suspend/disconnect handling. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/f0c71766-61e8-19b7-763a-5fbcdefc633d@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm/tests/drm_dp_mst_helper_test.c')
-rw-r--r--drivers/gpu/drm/tests/drm_dp_mst_helper_test.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
new file mode 100644
index 000000000000..1d2fade56227
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for the DRM DP MST helpers
+ *
+ * Copyright (c) 2022 MaĆ­ra Canal <mairacanal@riseup.net>
+ */
+
+#define PREFIX_STR "[drm_dp_mst_helper]"
+
+#include <kunit/test.h>
+
+#include <linux/random.h>
+
+#include <drm/display/drm_dp_mst_helper.h>
+#include <drm/drm_print.h>
+
+#include "../display/drm_dp_mst_topology_internal.h"
+
+static void igt_dp_mst_calc_pbn_mode(struct kunit *test)
+{
+ int pbn, i;
+ const struct {
+ int rate;
+ int bpp;
+ int expected;
+ bool dsc;
+ } test_params[] = {
+ { 154000, 30, 689, false },
+ { 234000, 30, 1047, false },
+ { 297000, 24, 1063, false },
+ { 332880, 24, 50, true },
+ { 324540, 24, 49, true },
+ };
+
+ for (i = 0; i < ARRAY_SIZE(test_params); i++) {
+ pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
+ test_params[i].bpp,
+ test_params[i].dsc);
+ KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
+ "Expected PBN %d for clock %d bpp %d, got %d\n",
+ test_params[i].expected, test_params[i].rate,
+ test_params[i].bpp, pbn);
+ }
+}
+
+static bool
+sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
+ const struct drm_dp_sideband_msg_req_body *out)
+{
+ const struct drm_dp_remote_i2c_read_tx *txin, *txout;
+ int i;
+
+ if (in->req_type != out->req_type)
+ return false;
+
+ switch (in->req_type) {
+ /*
+ * Compare struct members manually for request types which can't be
+ * compared simply using memcmp(). This is because said request types
+ * contain pointers to other allocated structs
+ */
+ case DP_REMOTE_I2C_READ:
+#define IN in->u.i2c_read
+#define OUT out->u.i2c_read
+ if (IN.num_bytes_read != OUT.num_bytes_read ||
+ IN.num_transactions != OUT.num_transactions ||
+ IN.port_number != OUT.port_number ||
+ IN.read_i2c_device_id != OUT.read_i2c_device_id)
+ return false;
+
+ for (i = 0; i < IN.num_transactions; i++) {
+ txin = &IN.transactions[i];
+ txout = &OUT.transactions[i];
+
+ if (txin->i2c_dev_id != txout->i2c_dev_id ||
+ txin->no_stop_bit != txout->no_stop_bit ||
+ txin->num_bytes != txout->num_bytes ||
+ txin->i2c_transaction_delay !=
+ txout->i2c_transaction_delay)
+ return false;
+
+ if (memcmp(txin->bytes, txout->bytes,
+ txin->num_bytes) != 0)
+ return false;
+ }
+ break;
+#undef IN
+#undef OUT
+
+ case DP_REMOTE_DPCD_WRITE:
+#define IN in->u.dpcd_write
+#define OUT out->u.dpcd_write
+ if (IN.dpcd_address != OUT.dpcd_address ||
+ IN.num_bytes != OUT.num_bytes ||
+ IN.port_number != OUT.port_number)
+ return false;
+
+ return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+ case DP_REMOTE_I2C_WRITE:
+#define IN in->u.i2c_write
+#define OUT out->u.i2c_write
+ if (IN.port_number != OUT.port_number ||
+ IN.write_i2c_device_id != OUT.write_i2c_device_id ||
+ IN.num_bytes != OUT.num_bytes)
+ return false;
+
+ return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
+#undef IN
+#undef OUT
+
+ default:
+ return memcmp(in, out, sizeof(*in)) == 0;
+ }
+
+ return true;
+}
+
+static bool
+sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
+{
+ struct drm_dp_sideband_msg_req_body *out;
+ struct drm_printer p = drm_err_printer(PREFIX_STR);
+ struct drm_dp_sideband_msg_tx *txmsg;
+ int i, ret;
+ bool result = true;
+
+ out = kzalloc(sizeof(*out), GFP_KERNEL);
+ if (!out)
+ return false;
+
+ txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
+ if (!txmsg) {
+ kfree(out);
+ return false;
+ }
+
+ drm_dp_encode_sideband_req(in, txmsg);
+ ret = drm_dp_decode_sideband_req(txmsg, out);
+ if (ret < 0) {
+ drm_printf(&p, "Failed to decode sideband request: %d\n",
+ ret);
+ result = false;
+ goto out;
+ }
+
+ if (!sideband_msg_req_equal(in, out)) {
+ drm_printf(&p, "Encode/decode failed, expected:\n");
+ drm_dp_dump_sideband_msg_req_body(in, 1, &p);
+ drm_printf(&p, "Got:\n");
+ drm_dp_dump_sideband_msg_req_body(out, 1, &p);
+ result = false;
+ goto out;
+ }
+
+ switch (in->req_type) {
+ case DP_REMOTE_DPCD_WRITE:
+ kfree(out->u.dpcd_write.bytes);
+ break;
+ case DP_REMOTE_I2C_READ:
+ for (i = 0; i < out->u.i2c_read.num_transactions; i++)
+ kfree(out->u.i2c_read.transactions[i].bytes);
+ break;
+ case DP_REMOTE_I2C_WRITE:
+ kfree(out->u.i2c_write.bytes);
+ break;
+ }
+
+ /* Clear everything but the req_type for the input */
+ memset(&in->u, 0, sizeof(in->u));
+
+out:
+ kfree(out);
+ kfree(txmsg);
+ return result;
+}
+
+static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test)
+{
+ struct drm_dp_sideband_msg_req_body in = { 0 };
+ u8 data[] = { 0xff, 0x0, 0xdd };
+ int i;
+
+ in.req_type = DP_ENUM_PATH_RESOURCES;
+ in.u.port_num.port_number = 5;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_POWER_UP_PHY;
+ in.u.port_num.port_number = 5;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_POWER_DOWN_PHY;
+ in.u.port_num.port_number = 5;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_ALLOCATE_PAYLOAD;
+ in.u.allocate_payload.number_sdp_streams = 3;
+ for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
+ in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.allocate_payload.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.allocate_payload.vcpi = 0x7f;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.allocate_payload.pbn = U16_MAX;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_QUERY_PAYLOAD;
+ in.u.query_payload.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.query_payload.vcpi = 0x7f;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_REMOTE_DPCD_READ;
+ in.u.dpcd_read.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.dpcd_read.dpcd_address = 0xfedcb;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.dpcd_read.num_bytes = U8_MAX;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_REMOTE_DPCD_WRITE;
+ in.u.dpcd_write.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.dpcd_write.dpcd_address = 0xfedcb;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
+ in.u.dpcd_write.bytes = data;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_REMOTE_I2C_READ;
+ in.u.i2c_read.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.i2c_read.read_i2c_device_id = 0x7f;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.i2c_read.num_transactions = 3;
+ in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
+ for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
+ in.u.i2c_read.transactions[i].bytes = data;
+ in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
+ in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
+ in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
+ }
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_REMOTE_I2C_WRITE;
+ in.u.i2c_write.port_number = 0xf;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.i2c_write.write_i2c_device_id = 0x7f;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
+ in.u.i2c_write.bytes = data;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+
+ in.req_type = DP_QUERY_STREAM_ENC_STATUS;
+ in.u.enc_status.stream_id = 1;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ get_random_bytes(in.u.enc_status.client_id,
+ sizeof(in.u.enc_status.client_id));
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.enc_status.stream_event = 3;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.enc_status.valid_stream_event = 0;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.enc_status.stream_behavior = 3;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ in.u.enc_status.valid_stream_behavior = 1;
+ KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+}
+
+static struct kunit_case drm_dp_mst_helper_tests[] = {
+ KUNIT_CASE(igt_dp_mst_calc_pbn_mode),
+ KUNIT_CASE(igt_dp_mst_sideband_msg_req_decode),
+ { }
+};
+
+static struct kunit_suite drm_dp_mst_helper_test_suite = {
+ .name = "drm_dp_mst_helper",
+ .test_cases = drm_dp_mst_helper_tests,
+};
+
+kunit_test_suite(drm_dp_mst_helper_test_suite);
+
+MODULE_LICENSE("GPL");