1 // SPDX-License-Identifier: GPL-2.0-only
3 * Test cases for the DRM DP MST helpers
8 #define PREFIX_STR "[drm_dp_mst_helper]"
10 #include <kunit/test.h>
12 #include <linux/random.h>
14 #include <drm/display/drm_dp_mst_helper.h>
15 #include <drm/drm_print.h>
17 #include "../display/drm_dp_mst_topology_internal.h"
19 static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
28 { 154000, 30, 689, false },
29 { 234000, 30, 1047, false },
30 { 297000, 24, 1063, false },
31 { 332880, 24, 50, true },
32 { 324540, 24, 49, true },
35 for (i = 0; i < ARRAY_SIZE(test_params); i++) {
36 pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
39 KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
40 "Expected PBN %d for clock %d bpp %d, got %d\n",
41 test_params[i].expected, test_params[i].rate,
42 test_params[i].bpp, pbn);
47 sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
48 const struct drm_dp_sideband_msg_req_body *out)
50 const struct drm_dp_remote_i2c_read_tx *txin, *txout;
53 if (in->req_type != out->req_type)
56 switch (in->req_type) {
58 * Compare struct members manually for request types which can't be
59 * compared simply using memcmp(). This is because said request types
60 * contain pointers to other allocated structs
62 case DP_REMOTE_I2C_READ:
63 #define IN in->u.i2c_read
64 #define OUT out->u.i2c_read
65 if (IN.num_bytes_read != OUT.num_bytes_read ||
66 IN.num_transactions != OUT.num_transactions ||
67 IN.port_number != OUT.port_number ||
68 IN.read_i2c_device_id != OUT.read_i2c_device_id)
71 for (i = 0; i < IN.num_transactions; i++) {
72 txin = &IN.transactions[i];
73 txout = &OUT.transactions[i];
75 if (txin->i2c_dev_id != txout->i2c_dev_id ||
76 txin->no_stop_bit != txout->no_stop_bit ||
77 txin->num_bytes != txout->num_bytes ||
78 txin->i2c_transaction_delay !=
79 txout->i2c_transaction_delay)
82 if (memcmp(txin->bytes, txout->bytes,
83 txin->num_bytes) != 0)
90 case DP_REMOTE_DPCD_WRITE:
91 #define IN in->u.dpcd_write
92 #define OUT out->u.dpcd_write
93 if (IN.dpcd_address != OUT.dpcd_address ||
94 IN.num_bytes != OUT.num_bytes ||
95 IN.port_number != OUT.port_number)
98 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
102 case DP_REMOTE_I2C_WRITE:
103 #define IN in->u.i2c_write
104 #define OUT out->u.i2c_write
105 if (IN.port_number != OUT.port_number ||
106 IN.write_i2c_device_id != OUT.write_i2c_device_id ||
107 IN.num_bytes != OUT.num_bytes)
110 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
115 return memcmp(in, out, sizeof(*in)) == 0;
122 sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
124 struct drm_dp_sideband_msg_req_body *out;
125 struct drm_printer p = drm_err_printer(PREFIX_STR);
126 struct drm_dp_sideband_msg_tx *txmsg;
130 out = kzalloc(sizeof(*out), GFP_KERNEL);
134 txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
140 drm_dp_encode_sideband_req(in, txmsg);
141 ret = drm_dp_decode_sideband_req(txmsg, out);
143 drm_printf(&p, "Failed to decode sideband request: %d\n",
149 if (!sideband_msg_req_equal(in, out)) {
150 drm_printf(&p, "Encode/decode failed, expected:\n");
151 drm_dp_dump_sideband_msg_req_body(in, 1, &p);
152 drm_printf(&p, "Got:\n");
153 drm_dp_dump_sideband_msg_req_body(out, 1, &p);
158 switch (in->req_type) {
159 case DP_REMOTE_DPCD_WRITE:
160 kfree(out->u.dpcd_write.bytes);
162 case DP_REMOTE_I2C_READ:
163 for (i = 0; i < out->u.i2c_read.num_transactions; i++)
164 kfree(out->u.i2c_read.transactions[i].bytes);
166 case DP_REMOTE_I2C_WRITE:
167 kfree(out->u.i2c_write.bytes);
171 /* Clear everything but the req_type for the input */
172 memset(&in->u, 0, sizeof(in->u));
180 static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
182 struct drm_dp_sideband_msg_req_body in = { 0 };
183 u8 data[] = { 0xff, 0x0, 0xdd };
186 in.req_type = DP_ENUM_PATH_RESOURCES;
187 in.u.port_num.port_number = 5;
188 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
190 in.req_type = DP_POWER_UP_PHY;
191 in.u.port_num.port_number = 5;
192 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
194 in.req_type = DP_POWER_DOWN_PHY;
195 in.u.port_num.port_number = 5;
196 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
198 in.req_type = DP_ALLOCATE_PAYLOAD;
199 in.u.allocate_payload.number_sdp_streams = 3;
200 for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
201 in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
202 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
203 in.u.allocate_payload.port_number = 0xf;
204 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
205 in.u.allocate_payload.vcpi = 0x7f;
206 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
207 in.u.allocate_payload.pbn = U16_MAX;
208 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
210 in.req_type = DP_QUERY_PAYLOAD;
211 in.u.query_payload.port_number = 0xf;
212 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
213 in.u.query_payload.vcpi = 0x7f;
214 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
216 in.req_type = DP_REMOTE_DPCD_READ;
217 in.u.dpcd_read.port_number = 0xf;
218 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
219 in.u.dpcd_read.dpcd_address = 0xfedcb;
220 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
221 in.u.dpcd_read.num_bytes = U8_MAX;
222 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
224 in.req_type = DP_REMOTE_DPCD_WRITE;
225 in.u.dpcd_write.port_number = 0xf;
226 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
227 in.u.dpcd_write.dpcd_address = 0xfedcb;
228 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
229 in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
230 in.u.dpcd_write.bytes = data;
231 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
233 in.req_type = DP_REMOTE_I2C_READ;
234 in.u.i2c_read.port_number = 0xf;
235 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
236 in.u.i2c_read.read_i2c_device_id = 0x7f;
237 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
238 in.u.i2c_read.num_transactions = 3;
239 in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
240 for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
241 in.u.i2c_read.transactions[i].bytes = data;
242 in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
243 in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
244 in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
246 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
248 in.req_type = DP_REMOTE_I2C_WRITE;
249 in.u.i2c_write.port_number = 0xf;
250 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
251 in.u.i2c_write.write_i2c_device_id = 0x7f;
252 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
253 in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
254 in.u.i2c_write.bytes = data;
255 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
257 in.req_type = DP_QUERY_STREAM_ENC_STATUS;
258 in.u.enc_status.stream_id = 1;
259 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
260 get_random_bytes(in.u.enc_status.client_id,
261 sizeof(in.u.enc_status.client_id));
262 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
263 in.u.enc_status.stream_event = 3;
264 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
265 in.u.enc_status.valid_stream_event = 0;
266 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
267 in.u.enc_status.stream_behavior = 3;
268 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
269 in.u.enc_status.valid_stream_behavior = 1;
270 KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
273 static struct kunit_case drm_dp_mst_helper_tests[] = {
274 KUNIT_CASE(drm_test_dp_mst_calc_pbn_mode),
275 KUNIT_CASE(drm_test_dp_mst_sideband_msg_req_decode),
279 static struct kunit_suite drm_dp_mst_helper_test_suite = {
280 .name = "drm_dp_mst_helper",
281 .test_cases = drm_dp_mst_helper_tests,
284 kunit_test_suite(drm_dp_mst_helper_test_suite);
286 MODULE_LICENSE("GPL");