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