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