1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Test cases for for the DRM DP MST helpers
4  */
5 
6 #define PREFIX_STR "[drm_dp_mst_helper]"
7 
8 #include <linux/random.h>
9 
10 #include <drm/drm_dp_mst_helper.h>
11 #include <drm/drm_print.h>
12 
13 #include "../drm_dp_mst_topology_internal.h"
14 #include "test-drm_modeset_common.h"
15 
igt_dp_mst_calc_pbn_mode(void * ignored)16 int igt_dp_mst_calc_pbn_mode(void *ignored)
17 {
18 	int pbn, i;
19 	const struct {
20 		int rate;
21 		int bpp;
22 		int expected;
23 		bool dsc;
24 	} test_params[] = {
25 		{ 154000, 30, 689, false },
26 		{ 234000, 30, 1047, false },
27 		{ 297000, 24, 1063, false },
28 		{ 332880, 24, 50, true },
29 		{ 324540, 24, 49, true },
30 	};
31 
32 	for (i = 0; i < ARRAY_SIZE(test_params); i++) {
33 		pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
34 					   test_params[i].bpp,
35 					   test_params[i].dsc);
36 		FAIL(pbn != test_params[i].expected,
37 		     "Expected PBN %d for clock %d bpp %d, got %d\n",
38 		     test_params[i].expected, test_params[i].rate,
39 		     test_params[i].bpp, pbn);
40 	}
41 
42 	return 0;
43 }
44 
45 static bool
sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body * in,const struct drm_dp_sideband_msg_req_body * out)46 sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
47 		       const struct drm_dp_sideband_msg_req_body *out)
48 {
49 	const struct drm_dp_remote_i2c_read_tx *txin, *txout;
50 	int i;
51 
52 	if (in->req_type != out->req_type)
53 		return false;
54 
55 	switch (in->req_type) {
56 	/*
57 	 * Compare struct members manually for request types which can't be
58 	 * compared simply using memcmp(). This is because said request types
59 	 * contain pointers to other allocated structs
60 	 */
61 	case DP_REMOTE_I2C_READ:
62 #define IN in->u.i2c_read
63 #define OUT out->u.i2c_read
64 		if (IN.num_bytes_read != OUT.num_bytes_read ||
65 		    IN.num_transactions != OUT.num_transactions ||
66 		    IN.port_number != OUT.port_number ||
67 		    IN.read_i2c_device_id != OUT.read_i2c_device_id)
68 			return false;
69 
70 		for (i = 0; i < IN.num_transactions; i++) {
71 			txin = &IN.transactions[i];
72 			txout = &OUT.transactions[i];
73 
74 			if (txin->i2c_dev_id != txout->i2c_dev_id ||
75 			    txin->no_stop_bit != txout->no_stop_bit ||
76 			    txin->num_bytes != txout->num_bytes ||
77 			    txin->i2c_transaction_delay !=
78 			    txout->i2c_transaction_delay)
79 				return false;
80 
81 			if (memcmp(txin->bytes, txout->bytes,
82 				   txin->num_bytes) != 0)
83 				return false;
84 		}
85 		break;
86 #undef IN
87 #undef OUT
88 
89 	case DP_REMOTE_DPCD_WRITE:
90 #define IN in->u.dpcd_write
91 #define OUT out->u.dpcd_write
92 		if (IN.dpcd_address != OUT.dpcd_address ||
93 		    IN.num_bytes != OUT.num_bytes ||
94 		    IN.port_number != OUT.port_number)
95 			return false;
96 
97 		return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
98 #undef IN
99 #undef OUT
100 
101 	case DP_REMOTE_I2C_WRITE:
102 #define IN in->u.i2c_write
103 #define OUT out->u.i2c_write
104 		if (IN.port_number != OUT.port_number ||
105 		    IN.write_i2c_device_id != OUT.write_i2c_device_id ||
106 		    IN.num_bytes != OUT.num_bytes)
107 			return false;
108 
109 		return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
110 #undef IN
111 #undef OUT
112 
113 	default:
114 		return memcmp(in, out, sizeof(*in)) == 0;
115 	}
116 
117 	return true;
118 }
119 
120 static bool
sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body * in)121 sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
122 {
123 	struct drm_dp_sideband_msg_req_body *out;
124 	struct drm_printer p = drm_err_printer(PREFIX_STR);
125 	struct drm_dp_sideband_msg_tx *txmsg;
126 	int i, ret;
127 	bool result = true;
128 
129 	out = kzalloc(sizeof(*out), GFP_KERNEL);
130 	if (!out)
131 		return false;
132 
133 	txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
134 	if (!txmsg)
135 		return false;
136 
137 	drm_dp_encode_sideband_req(in, txmsg);
138 	ret = drm_dp_decode_sideband_req(txmsg, out);
139 	if (ret < 0) {
140 		drm_printf(&p, "Failed to decode sideband request: %d\n",
141 			   ret);
142 		result = false;
143 		goto out;
144 	}
145 
146 	if (!sideband_msg_req_equal(in, out)) {
147 		drm_printf(&p, "Encode/decode failed, expected:\n");
148 		drm_dp_dump_sideband_msg_req_body(in, 1, &p);
149 		drm_printf(&p, "Got:\n");
150 		drm_dp_dump_sideband_msg_req_body(out, 1, &p);
151 		result = false;
152 		goto out;
153 	}
154 
155 	switch (in->req_type) {
156 	case DP_REMOTE_DPCD_WRITE:
157 		kfree(out->u.dpcd_write.bytes);
158 		break;
159 	case DP_REMOTE_I2C_READ:
160 		for (i = 0; i < out->u.i2c_read.num_transactions; i++)
161 			kfree(out->u.i2c_read.transactions[i].bytes);
162 		break;
163 	case DP_REMOTE_I2C_WRITE:
164 		kfree(out->u.i2c_write.bytes);
165 		break;
166 	}
167 
168 	/* Clear everything but the req_type for the input */
169 	memset(&in->u, 0, sizeof(in->u));
170 
171 out:
172 	kfree(out);
173 	kfree(txmsg);
174 	return result;
175 }
176 
igt_dp_mst_sideband_msg_req_decode(void * unused)177 int igt_dp_mst_sideband_msg_req_decode(void *unused)
178 {
179 	struct drm_dp_sideband_msg_req_body in = { 0 };
180 	u8 data[] = { 0xff, 0x0, 0xdd };
181 	int i;
182 
183 #define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
184 
185 	in.req_type = DP_ENUM_PATH_RESOURCES;
186 	in.u.port_num.port_number = 5;
187 	DO_TEST();
188 
189 	in.req_type = DP_POWER_UP_PHY;
190 	in.u.port_num.port_number = 5;
191 	DO_TEST();
192 
193 	in.req_type = DP_POWER_DOWN_PHY;
194 	in.u.port_num.port_number = 5;
195 	DO_TEST();
196 
197 	in.req_type = DP_ALLOCATE_PAYLOAD;
198 	in.u.allocate_payload.number_sdp_streams = 3;
199 	for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
200 		in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
201 	DO_TEST();
202 	in.u.allocate_payload.port_number = 0xf;
203 	DO_TEST();
204 	in.u.allocate_payload.vcpi = 0x7f;
205 	DO_TEST();
206 	in.u.allocate_payload.pbn = U16_MAX;
207 	DO_TEST();
208 
209 	in.req_type = DP_QUERY_PAYLOAD;
210 	in.u.query_payload.port_number = 0xf;
211 	DO_TEST();
212 	in.u.query_payload.vcpi = 0x7f;
213 	DO_TEST();
214 
215 	in.req_type = DP_REMOTE_DPCD_READ;
216 	in.u.dpcd_read.port_number = 0xf;
217 	DO_TEST();
218 	in.u.dpcd_read.dpcd_address = 0xfedcb;
219 	DO_TEST();
220 	in.u.dpcd_read.num_bytes = U8_MAX;
221 	DO_TEST();
222 
223 	in.req_type = DP_REMOTE_DPCD_WRITE;
224 	in.u.dpcd_write.port_number = 0xf;
225 	DO_TEST();
226 	in.u.dpcd_write.dpcd_address = 0xfedcb;
227 	DO_TEST();
228 	in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
229 	in.u.dpcd_write.bytes = data;
230 	DO_TEST();
231 
232 	in.req_type = DP_REMOTE_I2C_READ;
233 	in.u.i2c_read.port_number = 0xf;
234 	DO_TEST();
235 	in.u.i2c_read.read_i2c_device_id = 0x7f;
236 	DO_TEST();
237 	in.u.i2c_read.num_transactions = 3;
238 	in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
239 	for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
240 		in.u.i2c_read.transactions[i].bytes = data;
241 		in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
242 		in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
243 		in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
244 	}
245 	DO_TEST();
246 
247 	in.req_type = DP_REMOTE_I2C_WRITE;
248 	in.u.i2c_write.port_number = 0xf;
249 	DO_TEST();
250 	in.u.i2c_write.write_i2c_device_id = 0x7f;
251 	DO_TEST();
252 	in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
253 	in.u.i2c_write.bytes = data;
254 	DO_TEST();
255 
256 	in.req_type = DP_QUERY_STREAM_ENC_STATUS;
257 	in.u.enc_status.stream_id = 1;
258 	DO_TEST();
259 	get_random_bytes(in.u.enc_status.client_id,
260 			 sizeof(in.u.enc_status.client_id));
261 	DO_TEST();
262 	in.u.enc_status.stream_event = 3;
263 	DO_TEST();
264 	in.u.enc_status.valid_stream_event = 0;
265 	DO_TEST();
266 	in.u.enc_status.stream_behavior = 3;
267 	DO_TEST();
268 	in.u.enc_status.valid_stream_behavior = 1;
269 	DO_TEST();
270 
271 #undef DO_TEST
272 	return 0;
273 }
274