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