brintos

brintos / linux-shallow public Read only

0
0
Text · 13.5 KiB · 89cd9e4 Raw
593 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Test cases for the DRM DP MST helpers4 *5 * Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>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 15struct 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 22static 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 = 68928	},29	{30		.clock = 234000,31		.bpp = 30,32		.dsc = false,33		.expected = 104734	},35	{36		.clock = 297000,37		.bpp = 24,38		.dsc = false,39		.expected = 106340	},41	{42		.clock = 332880,43		.bpp = 24,44		.dsc = true,45		.expected = 119146	},47	{48		.clock = 324540,49		.bpp = 24,50		.dsc = true,51		.expected = 116152	},53};54 55static 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 << 4),60			params->expected);61}62 63static 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 68KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_cases,69		  dp_mst_calc_pbn_mode_desc);70 71struct drm_dp_mst_calc_pbn_div_test {72	int link_rate;73	int lane_count;74	fixed20_12 expected;75};76 77#define fp_init(__int, __frac) { \78	.full = (__int) * (1 << 12) + \79		(__frac) * (1 << 12) / 100000 \80}81 82static const struct drm_dp_mst_calc_pbn_div_test drm_dp_mst_calc_pbn_div_dp1_4_cases[] = {83	/*84	 * UHBR rates (DP Standard v2.1 2.7.6.3, specifying the rounded to85	 *             closest value to 2 decimal places):86	 * .expected = .link_rate * .lane_count * 0.9671 / 8 / 54 / 10087	 * DP1.4 rates (DP Standard v2.1 2.6.4.2):88	 * .expected = .link_rate * .lane_count * 0.8000 / 8 / 54 / 10089	 *90	 * truncated to 5 decimal places.91	 */92	{93		.link_rate = 2000000,94		.lane_count = 4,95		.expected = fp_init(179,  9259),  /* 179.09259 */96	},97	{98		.link_rate = 2000000,99		.lane_count = 2,100		.expected = fp_init(89, 54629),101	},102	{103		.link_rate = 2000000,104		.lane_count = 1,105		.expected = fp_init(44, 77314),106	},107	{108		.link_rate = 1350000,109		.lane_count = 4,110		.expected = fp_init(120, 88750),111	},112	{113		.link_rate = 1350000,114		.lane_count = 2,115		.expected = fp_init(60, 44375),116	},117	{118		.link_rate = 1350000,119		.lane_count = 1,120		.expected = fp_init(30, 22187),121	},122	{123		.link_rate = 1000000,124		.lane_count = 4,125		.expected = fp_init(89, 54629),126	},127	{128		.link_rate = 1000000,129		.lane_count = 2,130		.expected = fp_init(44, 77314),131	},132	{133		.link_rate = 1000000,134		.lane_count = 1,135		.expected = fp_init(22, 38657),136	},137	{138		.link_rate = 810000,139		.lane_count = 4,140		.expected = fp_init(60, 0),141	},142	{143		.link_rate = 810000,144		.lane_count = 2,145		.expected = fp_init(30, 0),146	},147	{148		.link_rate = 810000,149		.lane_count = 1,150		.expected = fp_init(15, 0),151	},152	{153		.link_rate = 540000,154		.lane_count = 4,155		.expected = fp_init(40, 0),156	},157	{158		.link_rate = 540000,159		.lane_count = 2,160		.expected = fp_init(20, 0),161	},162	{163		.link_rate = 540000,164		.lane_count = 1,165		.expected = fp_init(10, 0),166	},167	{168		.link_rate = 270000,169		.lane_count = 4,170		.expected = fp_init(20, 0),171	},172	{173		.link_rate = 270000,174		.lane_count = 2,175		.expected = fp_init(10, 0),176	},177	{178		.link_rate = 270000,179		.lane_count = 1,180		.expected = fp_init(5, 0),181	},182	{183		.link_rate = 162000,184		.lane_count = 4,185		.expected = fp_init(12, 0),186	},187	{188		.link_rate = 162000,189		.lane_count = 2,190		.expected = fp_init(6, 0),191	},192	{193		.link_rate = 162000,194		.lane_count = 1,195		.expected = fp_init(3, 0),196	},197};198 199static void drm_test_dp_mst_calc_pbn_div(struct kunit *test)200{201	const struct drm_dp_mst_calc_pbn_div_test *params = test->param_value;202	/* mgr->dev is only needed by drm_dbg_kms(), but it's not called for the test cases. */203	struct drm_dp_mst_topology_mgr *mgr = test->priv;204 205	KUNIT_EXPECT_EQ(test, drm_dp_get_vc_payload_bw(mgr, params->link_rate, params->lane_count).full,206			params->expected.full);207}208 209static void dp_mst_calc_pbn_div_desc(const struct drm_dp_mst_calc_pbn_div_test *t, char *desc)210{211	sprintf(desc, "Link rate %d lane count %d", t->link_rate, t->lane_count);212}213 214KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_div, drm_dp_mst_calc_pbn_div_dp1_4_cases,215		  dp_mst_calc_pbn_div_desc);216 217static u8 data[] = { 0xff, 0x00, 0xdd };218 219struct drm_dp_mst_sideband_msg_req_test {220	const char *desc;221	const struct drm_dp_sideband_msg_req_body in;222};223 224static const struct drm_dp_mst_sideband_msg_req_test drm_dp_mst_sideband_msg_req_cases[] = {225	{226		.desc = "DP_ENUM_PATH_RESOURCES with port number",227		.in = {228			.req_type = DP_ENUM_PATH_RESOURCES,229			.u.port_num.port_number = 5,230		},231	},232	{233		.desc = "DP_POWER_UP_PHY with port number",234		.in = {235			.req_type = DP_POWER_UP_PHY,236			.u.port_num.port_number = 5,237		},238	},239	{240		.desc = "DP_POWER_DOWN_PHY with port number",241		.in = {242			.req_type = DP_POWER_DOWN_PHY,243			.u.port_num.port_number = 5,244		},245	},246	{247		.desc = "DP_ALLOCATE_PAYLOAD with SDP stream sinks",248		.in = {249			.req_type = DP_ALLOCATE_PAYLOAD,250			.u.allocate_payload.number_sdp_streams = 3,251			.u.allocate_payload.sdp_stream_sink = { 1, 2, 3 },252		},253	},254	{255		.desc = "DP_ALLOCATE_PAYLOAD with port number",256		.in = {257			.req_type = DP_ALLOCATE_PAYLOAD,258			.u.allocate_payload.port_number = 0xf,259		},260	},261	{262		.desc = "DP_ALLOCATE_PAYLOAD with VCPI",263		.in = {264			.req_type = DP_ALLOCATE_PAYLOAD,265			.u.allocate_payload.vcpi = 0x7f,266		},267	},268	{269		.desc = "DP_ALLOCATE_PAYLOAD with PBN",270		.in = {271			.req_type = DP_ALLOCATE_PAYLOAD,272			.u.allocate_payload.pbn = U16_MAX,273		},274	},275	{276		.desc = "DP_QUERY_PAYLOAD with port number",277		.in = {278			.req_type = DP_QUERY_PAYLOAD,279			.u.query_payload.port_number = 0xf,280		},281	},282	{283		.desc = "DP_QUERY_PAYLOAD with VCPI",284		.in = {285			.req_type = DP_QUERY_PAYLOAD,286			.u.query_payload.vcpi = 0x7f,287		},288	},289	{290		.desc = "DP_REMOTE_DPCD_READ with port number",291		.in = {292			.req_type = DP_REMOTE_DPCD_READ,293			.u.dpcd_read.port_number = 0xf,294		},295	},296	{297		.desc = "DP_REMOTE_DPCD_READ with DPCD address",298		.in = {299			.req_type = DP_REMOTE_DPCD_READ,300			.u.dpcd_read.dpcd_address = 0xfedcb,301		},302	},303	{304		.desc = "DP_REMOTE_DPCD_READ with max number of bytes",305		.in = {306			.req_type = DP_REMOTE_DPCD_READ,307			.u.dpcd_read.num_bytes = U8_MAX,308		},309	},310	{311		.desc = "DP_REMOTE_DPCD_WRITE with port number",312		.in = {313			.req_type = DP_REMOTE_DPCD_WRITE,314			.u.dpcd_write.port_number = 0xf,315		},316	},317	{318		.desc = "DP_REMOTE_DPCD_WRITE with DPCD address",319		.in = {320			.req_type = DP_REMOTE_DPCD_WRITE,321			.u.dpcd_write.dpcd_address = 0xfedcb,322		},323	},324	{325		.desc = "DP_REMOTE_DPCD_WRITE with data array",326		.in = {327			.req_type = DP_REMOTE_DPCD_WRITE,328			.u.dpcd_write.num_bytes = ARRAY_SIZE(data),329			.u.dpcd_write.bytes = data,330		},331	},332	{333		.desc = "DP_REMOTE_I2C_READ with port number",334		.in = {335			.req_type = DP_REMOTE_I2C_READ,336			.u.i2c_read.port_number = 0xf,337		},338	},339	{340		.desc = "DP_REMOTE_I2C_READ with I2C device ID",341		.in = {342			.req_type = DP_REMOTE_I2C_READ,343			.u.i2c_read.read_i2c_device_id = 0x7f,344		},345	},346	{347		.desc = "DP_REMOTE_I2C_READ with transactions array",348		.in = {349			.req_type = DP_REMOTE_I2C_READ,350			.u.i2c_read.num_transactions = 3,351			.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3,352			.u.i2c_read.transactions = {353				{ .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7f,354				  .i2c_transaction_delay = 0xf, },355				{ .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7e,356				  .i2c_transaction_delay = 0xe, },357				{ .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7d,358				  .i2c_transaction_delay = 0xd, },359			},360		},361	},362	{363		.desc = "DP_REMOTE_I2C_WRITE with port number",364		.in = {365			.req_type = DP_REMOTE_I2C_WRITE,366			.u.i2c_write.port_number = 0xf,367		},368	},369	{370		.desc = "DP_REMOTE_I2C_WRITE with I2C device ID",371		.in = {372			.req_type = DP_REMOTE_I2C_WRITE,373			.u.i2c_write.write_i2c_device_id = 0x7f,374		},375	},376	{377		.desc = "DP_REMOTE_I2C_WRITE with data array",378		.in = {379			.req_type = DP_REMOTE_I2C_WRITE,380			.u.i2c_write.num_bytes = ARRAY_SIZE(data),381			.u.i2c_write.bytes = data,382		},383	},384	{385		.desc = "DP_QUERY_STREAM_ENC_STATUS with stream ID",386		.in = {387			.req_type = DP_QUERY_STREAM_ENC_STATUS,388			.u.enc_status.stream_id = 1,389		},390	},391	{392		.desc = "DP_QUERY_STREAM_ENC_STATUS with client ID",393		.in = {394			.req_type = DP_QUERY_STREAM_ENC_STATUS,395			.u.enc_status.client_id = { 0x4f, 0x7f, 0xb4, 0x00, 0x8c, 0x0d, 0x67 },396		},397	},398	{399		.desc = "DP_QUERY_STREAM_ENC_STATUS with stream event",400		.in = {401			.req_type = DP_QUERY_STREAM_ENC_STATUS,402			.u.enc_status.stream_event = 3,403		},404	},405	{406		.desc = "DP_QUERY_STREAM_ENC_STATUS with valid stream event",407		.in = {408			.req_type = DP_QUERY_STREAM_ENC_STATUS,409			.u.enc_status.valid_stream_event = 0,410		},411	},412	{413		.desc = "DP_QUERY_STREAM_ENC_STATUS with stream behavior",414		.in = {415			.req_type = DP_QUERY_STREAM_ENC_STATUS,416			.u.enc_status.stream_behavior = 3,417		},418	},419	{420		.desc = "DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior",421		.in = {422			.req_type = DP_QUERY_STREAM_ENC_STATUS,423			.u.enc_status.valid_stream_behavior = 1,424		}425	},426};427 428static bool429sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,430		       const struct drm_dp_sideband_msg_req_body *out)431{432	const struct drm_dp_remote_i2c_read_tx *txin, *txout;433	int i;434 435	if (in->req_type != out->req_type)436		return false;437 438	switch (in->req_type) {439	/*440	 * Compare struct members manually for request types which can't be441	 * compared simply using memcmp(). This is because said request types442	 * contain pointers to other allocated structs443	 */444	case DP_REMOTE_I2C_READ:445#define IN in->u.i2c_read446#define OUT out->u.i2c_read447		if (IN.num_bytes_read != OUT.num_bytes_read ||448		    IN.num_transactions != OUT.num_transactions ||449		    IN.port_number != OUT.port_number ||450		    IN.read_i2c_device_id != OUT.read_i2c_device_id)451			return false;452 453		for (i = 0; i < IN.num_transactions; i++) {454			txin = &IN.transactions[i];455			txout = &OUT.transactions[i];456 457			if (txin->i2c_dev_id != txout->i2c_dev_id ||458			    txin->no_stop_bit != txout->no_stop_bit ||459			    txin->num_bytes != txout->num_bytes ||460			    txin->i2c_transaction_delay !=461			    txout->i2c_transaction_delay)462				return false;463 464			if (memcmp(txin->bytes, txout->bytes,465				   txin->num_bytes) != 0)466				return false;467		}468		break;469#undef IN470#undef OUT471 472	case DP_REMOTE_DPCD_WRITE:473#define IN in->u.dpcd_write474#define OUT out->u.dpcd_write475		if (IN.dpcd_address != OUT.dpcd_address ||476		    IN.num_bytes != OUT.num_bytes ||477		    IN.port_number != OUT.port_number)478			return false;479 480		return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;481#undef IN482#undef OUT483 484	case DP_REMOTE_I2C_WRITE:485#define IN in->u.i2c_write486#define OUT out->u.i2c_write487		if (IN.port_number != OUT.port_number ||488		    IN.write_i2c_device_id != OUT.write_i2c_device_id ||489		    IN.num_bytes != OUT.num_bytes)490			return false;491 492		return memcmp(IN.bytes, OUT.bytes, IN.num_bytes) == 0;493#undef IN494#undef OUT495 496	default:497		return memcmp(in, out, sizeof(*in)) == 0;498	}499 500	return true;501}502 503static void drm_test_dp_mst_msg_printf(struct drm_printer *p, struct va_format *vaf)504{505	struct kunit *test = p->arg;506 507	kunit_err(test, "%pV", vaf);508}509 510static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)511{512	const struct drm_dp_mst_sideband_msg_req_test *params = test->param_value;513	const struct drm_dp_sideband_msg_req_body *in = &params->in;514	struct drm_dp_sideband_msg_req_body *out;515	struct drm_dp_sideband_msg_tx *txmsg;516	struct drm_printer p = {517		.printfn = drm_test_dp_mst_msg_printf,518		.arg = test519	};520	int i;521 522	out = kunit_kzalloc(test, sizeof(*out), GFP_KERNEL);523	KUNIT_ASSERT_NOT_NULL(test, out);524 525	txmsg = kunit_kzalloc(test, sizeof(*txmsg), GFP_KERNEL);526	KUNIT_ASSERT_NOT_NULL(test, txmsg);527 528	drm_dp_encode_sideband_req(in, txmsg);529	KUNIT_EXPECT_GE_MSG(test, drm_dp_decode_sideband_req(txmsg, out), 0,530			    "Failed to decode sideband request");531 532	if (!sideband_msg_req_equal(in, out)) {533		KUNIT_FAIL(test, "Encode/decode failed");534		kunit_err(test, "Expected:");535		drm_dp_dump_sideband_msg_req_body(in, 1, &p);536		kunit_err(test, "Got:");537		drm_dp_dump_sideband_msg_req_body(out, 1, &p);538	}539 540	switch (in->req_type) {541	case DP_REMOTE_DPCD_WRITE:542		kfree(out->u.dpcd_write.bytes);543		break;544	case DP_REMOTE_I2C_READ:545		for (i = 0; i < out->u.i2c_read.num_transactions; i++)546			kfree(out->u.i2c_read.transactions[i].bytes);547		break;548	case DP_REMOTE_I2C_WRITE:549		kfree(out->u.i2c_write.bytes);550		break;551	}552}553 554static void555drm_dp_mst_sideband_msg_req_desc(const struct drm_dp_mst_sideband_msg_req_test *t, char *desc)556{557	strcpy(desc, t->desc);558}559 560KUNIT_ARRAY_PARAM(drm_dp_mst_sideband_msg_req, drm_dp_mst_sideband_msg_req_cases,561		  drm_dp_mst_sideband_msg_req_desc);562 563static struct kunit_case drm_dp_mst_helper_tests[] = {564	KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_gen_params),565	KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_div, drm_dp_mst_calc_pbn_div_gen_params),566	KUNIT_CASE_PARAM(drm_test_dp_mst_sideband_msg_req_decode,567			 drm_dp_mst_sideband_msg_req_gen_params),568	{ }569};570 571static int drm_dp_mst_helper_tests_init(struct kunit *test)572{573	struct drm_dp_mst_topology_mgr *mgr;574 575	mgr = kunit_kzalloc(test, sizeof(*mgr), GFP_KERNEL);576	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, mgr);577 578	test->priv = mgr;579 580	return 0;581}582 583static struct kunit_suite drm_dp_mst_helper_test_suite = {584	.name = "drm_dp_mst_helper",585	.init = drm_dp_mst_helper_tests_init,586	.test_cases = drm_dp_mst_helper_tests,587};588 589kunit_test_suite(drm_dp_mst_helper_test_suite);590 591MODULE_DESCRIPTION("Test cases for the DRM DP MST helpers");592MODULE_LICENSE("GPL");593