]> Git Repo - linux.git/blob - drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
Merge tag 'fsnotify_for_v6.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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 #include <kunit/test.h>
9
10 #include <drm/display/drm_dp_mst_helper.h>
11 #include <drm/drm_print.h>
12
13 #include "../display/drm_dp_mst_topology_internal.h"
14
15 struct drm_dp_mst_calc_pbn_mode_test {
16         const int clock;
17         const int bpp;
18         const bool dsc;
19         const int expected;
20 };
21
22 static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases[] = {
23         {
24                 .clock = 154000,
25                 .bpp = 30,
26                 .dsc = false,
27                 .expected = 689
28         },
29         {
30                 .clock = 234000,
31                 .bpp = 30,
32                 .dsc = false,
33                 .expected = 1047
34         },
35         {
36                 .clock = 297000,
37                 .bpp = 24,
38                 .dsc = false,
39                 .expected = 1063
40         },
41         {
42                 .clock = 332880,
43                 .bpp = 24,
44                 .dsc = true,
45                 .expected = 50
46         },
47         {
48                 .clock = 324540,
49                 .bpp = 24,
50                 .dsc = true,
51                 .expected = 49
52         },
53 };
54
55 static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
56 {
57         const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
58
59         KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
60                         params->expected);
61 }
62
63 static void dp_mst_calc_pbn_mode_desc(const struct drm_dp_mst_calc_pbn_mode_test *t, char *desc)
64 {
65         sprintf(desc, "Clock %d BPP %d DSC %s", t->clock, t->bpp, t->dsc ? "enabled" : "disabled");
66 }
67
68 KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_cases,
69                   dp_mst_calc_pbn_mode_desc);
70
71 static u8 data[] = { 0xff, 0x00, 0xdd };
72
73 struct drm_dp_mst_sideband_msg_req_test {
74         const char *desc;
75         const struct drm_dp_sideband_msg_req_body in;
76 };
77
78 static const struct drm_dp_mst_sideband_msg_req_test drm_dp_mst_sideband_msg_req_cases[] = {
79         {
80                 .desc = "DP_ENUM_PATH_RESOURCES with port number",
81                 .in = {
82                         .req_type = DP_ENUM_PATH_RESOURCES,
83                         .u.port_num.port_number = 5,
84                 },
85         },
86         {
87                 .desc = "DP_POWER_UP_PHY with port number",
88                 .in = {
89                         .req_type = DP_POWER_UP_PHY,
90                         .u.port_num.port_number = 5,
91                 },
92         },
93         {
94                 .desc = "DP_POWER_DOWN_PHY with port number",
95                 .in = {
96                         .req_type = DP_POWER_DOWN_PHY,
97                         .u.port_num.port_number = 5,
98                 },
99         },
100         {
101                 .desc = "DP_ALLOCATE_PAYLOAD with SDP stream sinks",
102                 .in = {
103                         .req_type = DP_ALLOCATE_PAYLOAD,
104                         .u.allocate_payload.number_sdp_streams = 3,
105                         .u.allocate_payload.sdp_stream_sink = { 1, 2, 3 },
106                 },
107         },
108         {
109                 .desc = "DP_ALLOCATE_PAYLOAD with port number",
110                 .in = {
111                         .req_type = DP_ALLOCATE_PAYLOAD,
112                         .u.allocate_payload.port_number = 0xf,
113                 },
114         },
115         {
116                 .desc = "DP_ALLOCATE_PAYLOAD with VCPI",
117                 .in = {
118                         .req_type = DP_ALLOCATE_PAYLOAD,
119                         .u.allocate_payload.vcpi = 0x7f,
120                 },
121         },
122         {
123                 .desc = "DP_ALLOCATE_PAYLOAD with PBN",
124                 .in = {
125                         .req_type = DP_ALLOCATE_PAYLOAD,
126                         .u.allocate_payload.pbn = U16_MAX,
127                 },
128         },
129         {
130                 .desc = "DP_QUERY_PAYLOAD with port number",
131                 .in = {
132                         .req_type = DP_QUERY_PAYLOAD,
133                         .u.query_payload.port_number = 0xf,
134                 },
135         },
136         {
137                 .desc = "DP_QUERY_PAYLOAD with VCPI",
138                 .in = {
139                         .req_type = DP_QUERY_PAYLOAD,
140                         .u.query_payload.vcpi = 0x7f,
141                 },
142         },
143         {
144                 .desc = "DP_REMOTE_DPCD_READ with port number",
145                 .in = {
146                         .req_type = DP_REMOTE_DPCD_READ,
147                         .u.dpcd_read.port_number = 0xf,
148                 },
149         },
150         {
151                 .desc = "DP_REMOTE_DPCD_READ with DPCD address",
152                 .in = {
153                         .req_type = DP_REMOTE_DPCD_READ,
154                         .u.dpcd_read.dpcd_address = 0xfedcb,
155                 },
156         },
157         {
158                 .desc = "DP_REMOTE_DPCD_READ with max number of bytes",
159                 .in = {
160                         .req_type = DP_REMOTE_DPCD_READ,
161                         .u.dpcd_read.num_bytes = U8_MAX,
162                 },
163         },
164         {
165                 .desc = "DP_REMOTE_DPCD_WRITE with port number",
166                 .in = {
167                         .req_type = DP_REMOTE_DPCD_WRITE,
168                         .u.dpcd_write.port_number = 0xf,
169                 },
170         },
171         {
172                 .desc = "DP_REMOTE_DPCD_WRITE with DPCD address",
173                 .in = {
174                         .req_type = DP_REMOTE_DPCD_WRITE,
175                         .u.dpcd_write.dpcd_address = 0xfedcb,
176                 },
177         },
178         {
179                 .desc = "DP_REMOTE_DPCD_WRITE with data array",
180                 .in = {
181                         .req_type = DP_REMOTE_DPCD_WRITE,
182                         .u.dpcd_write.num_bytes = ARRAY_SIZE(data),
183                         .u.dpcd_write.bytes = data,
184                 },
185         },
186         {
187                 .desc = "DP_REMOTE_I2C_READ with port number",
188                 .in = {
189                         .req_type = DP_REMOTE_I2C_READ,
190                         .u.i2c_read.port_number = 0xf,
191                 },
192         },
193         {
194                 .desc = "DP_REMOTE_I2C_READ with I2C device ID",
195                 .in = {
196                         .req_type = DP_REMOTE_I2C_READ,
197                         .u.i2c_read.read_i2c_device_id = 0x7f,
198                 },
199         },
200         {
201                 .desc = "DP_REMOTE_I2C_READ with transactions array",
202                 .in = {
203                         .req_type = DP_REMOTE_I2C_READ,
204                         .u.i2c_read.num_transactions = 3,
205                         .u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3,
206                         .u.i2c_read.transactions = {
207                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7f,
208                                   .i2c_transaction_delay = 0xf, },
209                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7e,
210                                   .i2c_transaction_delay = 0xe, },
211                                 { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7d,
212                                   .i2c_transaction_delay = 0xd, },
213                         },
214                 },
215         },
216         {
217                 .desc = "DP_REMOTE_I2C_WRITE with port number",
218                 .in = {
219                         .req_type = DP_REMOTE_I2C_WRITE,
220                         .u.i2c_write.port_number = 0xf,
221                 },
222         },
223         {
224                 .desc = "DP_REMOTE_I2C_WRITE with I2C device ID",
225                 .in = {
226                         .req_type = DP_REMOTE_I2C_WRITE,
227                         .u.i2c_write.write_i2c_device_id = 0x7f,
228                 },
229         },
230         {
231                 .desc = "DP_REMOTE_I2C_WRITE with data array",
232                 .in = {
233                         .req_type = DP_REMOTE_I2C_WRITE,
234                         .u.i2c_write.num_bytes = ARRAY_SIZE(data),
235                         .u.i2c_write.bytes = data,
236                 },
237         },
238         {
239                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream ID",
240                 .in = {
241                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
242                         .u.enc_status.stream_id = 1,
243                 },
244         },
245         {
246                 .desc = "DP_QUERY_STREAM_ENC_STATUS with client ID",
247                 .in = {
248                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
249                         .u.enc_status.client_id = { 0x4f, 0x7f, 0xb4, 0x00, 0x8c, 0x0d, 0x67 },
250                 },
251         },
252         {
253                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream event",
254                 .in = {
255                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
256                         .u.enc_status.stream_event = 3,
257                 },
258         },
259         {
260                 .desc = "DP_QUERY_STREAM_ENC_STATUS with valid stream event",
261                 .in = {
262                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
263                         .u.enc_status.valid_stream_event = 0,
264                 },
265         },
266         {
267                 .desc = "DP_QUERY_STREAM_ENC_STATUS with stream behavior",
268                 .in = {
269                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
270                         .u.enc_status.stream_behavior = 3,
271                 },
272         },
273         {
274                 .desc = "DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior",
275                 .in = {
276                         .req_type = DP_QUERY_STREAM_ENC_STATUS,
277                         .u.enc_status.valid_stream_behavior = 1,
278                 }
279         },
280 };
281
282 static bool
283 sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
284                        const struct drm_dp_sideband_msg_req_body *out)
285 {
286         const struct drm_dp_remote_i2c_read_tx *txin, *txout;
287         int i;
288
289         if (in->req_type != out->req_type)
290                 return false;
291
292         switch (in->req_type) {
293         /*
294          * Compare struct members manually for request types which can't be
295          * compared simply using memcmp(). This is because said request types
296          * contain pointers to other allocated structs
297          */
298         case DP_REMOTE_I2C_READ:
299 #define IN in->u.i2c_read
300 #define OUT out->u.i2c_read
301                 if (IN.num_bytes_read != OUT.num_bytes_read ||
302                     IN.num_transactions != OUT.num_transactions ||
303                     IN.port_number != OUT.port_number ||
304                     IN.read_i2c_device_id != OUT.read_i2c_device_id)
305                         return false;
306
307                 for (i = 0; i < IN.num_transactions; i++) {
308                         txin = &IN.transactions[i];
309                         txout = &OUT.transactions[i];
310
311                         if (txin->i2c_dev_id != txout->i2c_dev_id ||
312                             txin->no_stop_bit != txout->no_stop_bit ||
313                             txin->num_bytes != txout->num_bytes ||
314                             txin->i2c_transaction_delay !=
315                             txout->i2c_transaction_delay)
316                                 return false;
317
318                         if (memcmp(txin->bytes, txout->bytes,
319                                    txin->num_bytes) != 0)
320                                 return false;
321                 }
322                 break;
323 #undef IN
324 #undef OUT
325
326         case DP_REMOTE_DPCD_WRITE:
327 #define IN in->u.dpcd_write
328 #define OUT out->u.dpcd_write
329                 if (IN.dpcd_address != OUT.dpcd_address ||
330                     IN.num_bytes != OUT.num_bytes ||
331                     IN.port_number != OUT.port_number)
332                         return false;
333
334                 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
335 #undef IN
336 #undef OUT
337
338         case DP_REMOTE_I2C_WRITE:
339 #define IN in->u.i2c_write
340 #define OUT out->u.i2c_write
341                 if (IN.port_number != OUT.port_number ||
342                     IN.write_i2c_device_id != OUT.write_i2c_device_id ||
343                     IN.num_bytes != OUT.num_bytes)
344                         return false;
345
346                 return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;
347 #undef IN
348 #undef OUT
349
350         default:
351                 return memcmp(in, out, sizeof(*in)) == 0;
352         }
353
354         return true;
355 }
356
357 static void drm_test_dp_mst_msg_printf(struct drm_printer *p, struct va_format *vaf)
358 {
359         struct kunit *test = p->arg;
360
361         kunit_err(test, "%pV", vaf);
362 }
363
364 static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
365 {
366         const struct drm_dp_mst_sideband_msg_req_test *params = test->param_value;
367         const struct drm_dp_sideband_msg_req_body *in = &params->in;
368         struct drm_dp_sideband_msg_req_body *out;
369         struct drm_dp_sideband_msg_tx *txmsg;
370         struct drm_printer p = {
371                 .printfn = drm_test_dp_mst_msg_printf,
372                 .arg = test
373         };
374         int i;
375
376         out = kunit_kzalloc(test, sizeof(*out), GFP_KERNEL);
377         KUNIT_ASSERT_NOT_NULL(test, out);
378
379         txmsg = kunit_kzalloc(test, sizeof(*txmsg), GFP_KERNEL);
380         KUNIT_ASSERT_NOT_NULL(test, txmsg);
381
382         drm_dp_encode_sideband_req(in, txmsg);
383         KUNIT_EXPECT_GE_MSG(test, drm_dp_decode_sideband_req(txmsg, out), 0,
384                             "Failed to decode sideband request");
385
386         if (!sideband_msg_req_equal(in, out)) {
387                 KUNIT_FAIL(test, "Encode/decode failed");
388                 kunit_err(test, "Expected:");
389                 drm_dp_dump_sideband_msg_req_body(in, 1, &p);
390                 kunit_err(test, "Got:");
391                 drm_dp_dump_sideband_msg_req_body(out, 1, &p);
392         }
393
394         switch (in->req_type) {
395         case DP_REMOTE_DPCD_WRITE:
396                 kfree(out->u.dpcd_write.bytes);
397                 break;
398         case DP_REMOTE_I2C_READ:
399                 for (i = 0; i < out->u.i2c_read.num_transactions; i++)
400                         kfree(out->u.i2c_read.transactions[i].bytes);
401                 break;
402         case DP_REMOTE_I2C_WRITE:
403                 kfree(out->u.i2c_write.bytes);
404                 break;
405         }
406 }
407
408 static void
409 drm_dp_mst_sideband_msg_req_desc(const struct drm_dp_mst_sideband_msg_req_test *t, char *desc)
410 {
411         strcpy(desc, t->desc);
412 }
413
414 KUNIT_ARRAY_PARAM(drm_dp_mst_sideband_msg_req, drm_dp_mst_sideband_msg_req_cases,
415                   drm_dp_mst_sideband_msg_req_desc);
416
417 static struct kunit_case drm_dp_mst_helper_tests[] = {
418         KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_gen_params),
419         KUNIT_CASE_PARAM(drm_test_dp_mst_sideband_msg_req_decode,
420                          drm_dp_mst_sideband_msg_req_gen_params),
421         { }
422 };
423
424 static struct kunit_suite drm_dp_mst_helper_test_suite = {
425         .name = "drm_dp_mst_helper",
426         .test_cases = drm_dp_mst_helper_tests,
427 };
428
429 kunit_test_suite(drm_dp_mst_helper_test_suite);
430
431 MODULE_LICENSE("GPL");
This page took 0.059922 seconds and 4 git commands to generate.