1 // SPDX-License-Identifier: GPL-2.0-only
3 * Test cases for for the DRM DP MST helpers
6 #define PREFIX_STR "[drm_dp_mst_helper]"
8 #include <linux/random.h>
10 #include <drm/drm_dp_mst_helper.h>
11 #include <drm/drm_print.h>
13 #include "../drm_dp_mst_topology_internal.h"
14 #include "test-drm_modeset_common.h"
16 int igt_dp_mst_calc_pbn_mode(void *ignored
)
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 },
32 for (i
= 0; i
< ARRAY_SIZE(test_params
); i
++) {
33 pbn
= drm_dp_calc_pbn_mode(test_params
[i
].rate
,
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
);
46 sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body
*in
,
47 const struct drm_dp_sideband_msg_req_body
*out
)
49 const struct drm_dp_remote_i2c_read_tx
*txin
, *txout
;
52 if (in
->req_type
!= out
->req_type
)
55 switch (in
->req_type
) {
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
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
)
70 for (i
= 0; i
< IN
.num_transactions
; i
++) {
71 txin
= &IN
.transactions
[i
];
72 txout
= &OUT
.transactions
[i
];
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
)
81 if (memcmp(txin
->bytes
, txout
->bytes
,
82 txin
->num_bytes
) != 0)
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
)
97 return memcmp(IN
.bytes
, OUT
.bytes
, IN
.num_bytes
) == 0;
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
)
109 return memcmp(IN
.bytes
, OUT
.bytes
, IN
.num_bytes
) == 0;
114 return memcmp(in
, out
, sizeof(*in
)) == 0;
121 sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body
*in
)
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
;
129 out
= kzalloc(sizeof(*out
), GFP_KERNEL
);
133 txmsg
= kzalloc(sizeof(*txmsg
), GFP_KERNEL
);
137 drm_dp_encode_sideband_req(in
, txmsg
);
138 ret
= drm_dp_decode_sideband_req(txmsg
, out
);
140 drm_printf(&p
, "Failed to decode sideband request: %d\n",
146 if (!sideband_msg_req_equal(in
, out
)) {
147 drm_printf(&p
, "Encode/decode failed, expected:\n");
148 drm_dp_dump_sideband_msg_req_body(in
, 1, &p
);
149 drm_printf(&p
, "Got:\n");
150 drm_dp_dump_sideband_msg_req_body(out
, 1, &p
);
155 switch (in
->req_type
) {
156 case DP_REMOTE_DPCD_WRITE
:
157 kfree(out
->u
.dpcd_write
.bytes
);
159 case DP_REMOTE_I2C_READ
:
160 for (i
= 0; i
< out
->u
.i2c_read
.num_transactions
; i
++)
161 kfree(out
->u
.i2c_read
.transactions
[i
].bytes
);
163 case DP_REMOTE_I2C_WRITE
:
164 kfree(out
->u
.i2c_write
.bytes
);
168 /* Clear everything but the req_type for the input */
169 memset(&in
->u
, 0, sizeof(in
->u
));
177 int igt_dp_mst_sideband_msg_req_decode(void *unused
)
179 struct drm_dp_sideband_msg_req_body in
= { 0 };
180 u8 data
[] = { 0xff, 0x0, 0xdd };
183 #define DO_TEST() FAIL_ON(!sideband_msg_req_encode_decode(&in))
185 in
.req_type
= DP_ENUM_PATH_RESOURCES
;
186 in
.u
.port_num
.port_number
= 5;
189 in
.req_type
= DP_POWER_UP_PHY
;
190 in
.u
.port_num
.port_number
= 5;
193 in
.req_type
= DP_POWER_DOWN_PHY
;
194 in
.u
.port_num
.port_number
= 5;
197 in
.req_type
= DP_ALLOCATE_PAYLOAD
;
198 in
.u
.allocate_payload
.number_sdp_streams
= 3;
199 for (i
= 0; i
< in
.u
.allocate_payload
.number_sdp_streams
; i
++)
200 in
.u
.allocate_payload
.sdp_stream_sink
[i
] = i
+ 1;
202 in
.u
.allocate_payload
.port_number
= 0xf;
204 in
.u
.allocate_payload
.vcpi
= 0x7f;
206 in
.u
.allocate_payload
.pbn
= U16_MAX
;
209 in
.req_type
= DP_QUERY_PAYLOAD
;
210 in
.u
.query_payload
.port_number
= 0xf;
212 in
.u
.query_payload
.vcpi
= 0x7f;
215 in
.req_type
= DP_REMOTE_DPCD_READ
;
216 in
.u
.dpcd_read
.port_number
= 0xf;
218 in
.u
.dpcd_read
.dpcd_address
= 0xfedcb;
220 in
.u
.dpcd_read
.num_bytes
= U8_MAX
;
223 in
.req_type
= DP_REMOTE_DPCD_WRITE
;
224 in
.u
.dpcd_write
.port_number
= 0xf;
226 in
.u
.dpcd_write
.dpcd_address
= 0xfedcb;
228 in
.u
.dpcd_write
.num_bytes
= ARRAY_SIZE(data
);
229 in
.u
.dpcd_write
.bytes
= data
;
232 in
.req_type
= DP_REMOTE_I2C_READ
;
233 in
.u
.i2c_read
.port_number
= 0xf;
235 in
.u
.i2c_read
.read_i2c_device_id
= 0x7f;
237 in
.u
.i2c_read
.num_transactions
= 3;
238 in
.u
.i2c_read
.num_bytes_read
= ARRAY_SIZE(data
) * 3;
239 for (i
= 0; i
< in
.u
.i2c_read
.num_transactions
; i
++) {
240 in
.u
.i2c_read
.transactions
[i
].bytes
= data
;
241 in
.u
.i2c_read
.transactions
[i
].num_bytes
= ARRAY_SIZE(data
);
242 in
.u
.i2c_read
.transactions
[i
].i2c_dev_id
= 0x7f & ~i
;
243 in
.u
.i2c_read
.transactions
[i
].i2c_transaction_delay
= 0xf & ~i
;
247 in
.req_type
= DP_REMOTE_I2C_WRITE
;
248 in
.u
.i2c_write
.port_number
= 0xf;
250 in
.u
.i2c_write
.write_i2c_device_id
= 0x7f;
252 in
.u
.i2c_write
.num_bytes
= ARRAY_SIZE(data
);
253 in
.u
.i2c_write
.bytes
= data
;
256 in
.req_type
= DP_QUERY_STREAM_ENC_STATUS
;
257 in
.u
.enc_status
.stream_id
= 1;
259 get_random_bytes(in
.u
.enc_status
.client_id
,
260 sizeof(in
.u
.enc_status
.client_id
));
262 in
.u
.enc_status
.stream_event
= 3;
264 in
.u
.enc_status
.valid_stream_event
= 0;
266 in
.u
.enc_status
.stream_behavior
= 3;
268 in
.u
.enc_status
.valid_stream_behavior
= 1;