Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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/dp/drm_dp_mst_helper.h>
11#include <drm/drm_print.h>
12
13#include "../dp/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 kfree(out);
136 return false;
137 }
138
139 drm_dp_encode_sideband_req(in, txmsg);
140 ret = drm_dp_decode_sideband_req(txmsg, out);
141 if (ret < 0) {
142 drm_printf(&p, "Failed to decode sideband request: %d\n",
143 ret);
144 result = false;
145 goto out;
146 }
147
148 if (!sideband_msg_req_equal(in, out)) {
149 drm_printf(&p, "Encode/decode failed, expected:\n");
150 drm_dp_dump_sideband_msg_req_body(in, 1, &p);
151 drm_printf(&p, "Got:\n");
152 drm_dp_dump_sideband_msg_req_body(out, 1, &p);
153 result = false;
154 goto out;
155 }
156
157 switch (in->req_type) {
158 case DP_REMOTE_DPCD_WRITE:
159 kfree(out->u.dpcd_write.bytes);
160 break;
161 case DP_REMOTE_I2C_READ:
162 for (i = 0; i < out->u.i2c_read.num_transactions; i++)
163 kfree(out->u.i2c_read.transactions[i].bytes);
164 break;
165 case DP_REMOTE_I2C_WRITE:
166 kfree(out->u.i2c_write.bytes);
167 break;
168 }
169
170 /* Clear everything but the req_type for the input */
171 memset(&in->u, 0, sizeof(in->u));
172
173out:
174 kfree(out);
175 kfree(txmsg);
176 return result;
177}
178
179int igt_dp_mst_sideband_msg_req_decode(void *unused)
180{
181 struct drm_dp_sideband_msg_req_body in = { 0 };
182 u8 data[] = { 0xff, 0x0, 0xdd };
183 int i;
184
185#define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
186
187 in.req_type = DP_ENUM_PATH_RESOURCES;
188 in.u.port_num.port_number = 5;
189 DO_TEST();
190
191 in.req_type = DP_POWER_UP_PHY;
192 in.u.port_num.port_number = 5;
193 DO_TEST();
194
195 in.req_type = DP_POWER_DOWN_PHY;
196 in.u.port_num.port_number = 5;
197 DO_TEST();
198
199 in.req_type = DP_ALLOCATE_PAYLOAD;
200 in.u.allocate_payload.number_sdp_streams = 3;
201 for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
202 in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
203 DO_TEST();
204 in.u.allocate_payload.port_number = 0xf;
205 DO_TEST();
206 in.u.allocate_payload.vcpi = 0x7f;
207 DO_TEST();
208 in.u.allocate_payload.pbn = U16_MAX;
209 DO_TEST();
210
211 in.req_type = DP_QUERY_PAYLOAD;
212 in.u.query_payload.port_number = 0xf;
213 DO_TEST();
214 in.u.query_payload.vcpi = 0x7f;
215 DO_TEST();
216
217 in.req_type = DP_REMOTE_DPCD_READ;
218 in.u.dpcd_read.port_number = 0xf;
219 DO_TEST();
220 in.u.dpcd_read.dpcd_address = 0xfedcb;
221 DO_TEST();
222 in.u.dpcd_read.num_bytes = U8_MAX;
223 DO_TEST();
224
225 in.req_type = DP_REMOTE_DPCD_WRITE;
226 in.u.dpcd_write.port_number = 0xf;
227 DO_TEST();
228 in.u.dpcd_write.dpcd_address = 0xfedcb;
229 DO_TEST();
230 in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
231 in.u.dpcd_write.bytes = data;
232 DO_TEST();
233
234 in.req_type = DP_REMOTE_I2C_READ;
235 in.u.i2c_read.port_number = 0xf;
236 DO_TEST();
237 in.u.i2c_read.read_i2c_device_id = 0x7f;
238 DO_TEST();
239 in.u.i2c_read.num_transactions = 3;
240 in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
241 for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
242 in.u.i2c_read.transactions[i].bytes = data;
243 in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
244 in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
245 in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
246 }
247 DO_TEST();
248
249 in.req_type = DP_REMOTE_I2C_WRITE;
250 in.u.i2c_write.port_number = 0xf;
251 DO_TEST();
252 in.u.i2c_write.write_i2c_device_id = 0x7f;
253 DO_TEST();
254 in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
255 in.u.i2c_write.bytes = data;
256 DO_TEST();
257
258 in.req_type = DP_QUERY_STREAM_ENC_STATUS;
259 in.u.enc_status.stream_id = 1;
260 DO_TEST();
261 get_random_bytes(in.u.enc_status.client_id,
262 sizeof(in.u.enc_status.client_id));
263 DO_TEST();
264 in.u.enc_status.stream_event = 3;
265 DO_TEST();
266 in.u.enc_status.valid_stream_event = 0;
267 DO_TEST();
268 in.u.enc_status.stream_behavior = 3;
269 DO_TEST();
270 in.u.enc_status.valid_stream_behavior = 1;
271 DO_TEST();
272
273#undef DO_TEST
274 return 0;
275}