Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 16int 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
 45static bool
 46sideband_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
120static bool
121sideband_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
171out:
172	kfree(out);
173	kfree(txmsg);
174	return result;
175}
176
177int 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}