[igt-dev] [PATCH i-g-t v2 1/2] tests/kms_content_protection: Add MST subtests

Anshuman Gupta anshuman.gupta at intel.com
Fri Oct 23 10:54:44 UTC 2020


On 2020-10-23 at 15:37:08 +0530, Karthik B S wrote:
> Add subtests to verify content protection simultaneously on
> multiple outputs on the same MST topology.
> 
> Signed-off-by: Anshuman Gupta <anshuman.gupta at intel.com>
> Signed-off-by: Karthik B S <karthik.b.s at intel.com>
> ---
>  tests/kms_content_protection.c | 220 +++++++++++++++++++++++++++++++++
>  1 file changed, 220 insertions(+)
> 
> diff --git a/tests/kms_content_protection.c b/tests/kms_content_protection.c
> index 303ed418..5807f3a3 100644
> --- a/tests/kms_content_protection.c
> +++ b/tests/kms_content_protection.c
> @@ -42,6 +42,12 @@ struct data {
>  	struct udev_monitor *uevent_monitor;
>  } data;
>  
> +typedef struct {
> +	float red;
> +	float green;
> +	float blue;
> +} color_t;
> +
>  /* Test flags */
>  #define CP_DPMS					(1 << 0)
>  #define CP_LIC					(1 << 1)
> @@ -457,6 +463,54 @@ static bool sink_hdcp2_capable(igt_output_t *output)
>  
>  	return strstr(buf, "HDCP2.2");
>  }
> +color_t red  = { 1.0f, 0.0f, 0.0f };
> +color_t green  = { 0.0f, 0.1f, 0.0f };
> +
> +static void prepare_modeset_on_mst_output(igt_output_t *output, enum pipe pipe)
> +{
> +	drmModeConnectorPtr c = output->config.connector;
> +	igt_display_t *display = &data.display;
> +	drmModeModeInfo *mode;
> +	igt_plane_t *primary;
> +	int i;
> +
> +	mode = igt_output_get_mode(output);
> +
> +	/*
> +	 * TODO: Add logic to use the highest possible modes on each output.
> +	 * Currently using 2k modes by default on all the outputs.
> +	 */
> +	igt_debug("Before mode override: Output %s Mode hdisplay %d Mode vdisplay %d\n",
> +		   output->name, mode->hdisplay, mode->vdisplay);
> +
> +	if (mode->hdisplay > 1920 && mode->vdisplay > 1080) {
> +		for (i = 0; i < c->count_modes; i++) {
> +			if (c->modes[i].hdisplay <= 1920 && c->modes[i].vdisplay <= 1080) {
> +				mode = &c->modes[i];
> +				igt_output_override_mode(output, mode);
> +				break;
> +			}
> +		}
> +	}
> +
> +	igt_debug("After mode overide: Output %s Mode hdisplay %d Mode vdisplay %d\n",
> +		   output->name, mode->hdisplay, mode->vdisplay);
> +
> +	if (pipe % 2) {
> +		igt_create_color_fb(display->drm_fd, mode->hdisplay, mode->vdisplay,
> +				    DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
> +				    red.red, red.blue, red.green, &data.red);
> +	} else {
> +		igt_create_color_fb(display->drm_fd, mode->hdisplay, mode->vdisplay,
> +				    DRM_FORMAT_XRGB8888, LOCAL_DRM_FORMAT_MOD_NONE,
> +				    green.red, green.blue, green.green, &data.green);
> +	}
> +
> +	igt_output_set_pipe(output, pipe);
> +	primary = igt_output_get_plane_type(output, DRM_PLANE_TYPE_PRIMARY);
> +	igt_plane_set_fb(primary, NULL);
> +	igt_plane_set_fb(primary, pipe % 2 ? &data.red : &data.green);
> +}
>  
>  static void
>  test_content_protection(enum igt_commit_style s, int content_type)
> @@ -496,6 +550,149 @@ test_content_protection(enum igt_commit_style s, int content_type)
>  	igt_require_f(valid_tests, "No connector found with HDCP capability\n");
>  }
>  
> +static bool is_output_support_cp_capable(igt_output_t *output, int content_type)
> +{
> +		if (!output->props[IGT_CONNECTOR_CONTENT_PROTECTION])
> +			return false;
> +
> +		if (!output->props[IGT_CONNECTOR_HDCP_CONTENT_TYPE] &&
> +		    content_type)
> +			return false;
> +
> +		if (content_type && !sink_hdcp2_capable(output)) {
> +			igt_info("\tSkip %s (Sink has no HDCP2.2 support)\n",
> +				 output->name);
> +			return false;
> +		} else if (!sink_hdcp_capable(output)) {
> +			igt_info("\tSkip %s (Sink has no HDCP support)\n",
> +				 output->name);
> +			return false;
> +		}
> +
> +		return true;
> +}
> +
> +static int parse_path_blob(char *blob_data)
> +{
> +	int connector_id;
> +	char *encoder;
> +
> +	encoder = strtok(blob_data, ":");
> +	igt_assert_f(!strcmp(encoder, "mst"), "PATH connector property expected to have 'mst'\n");
> +
> +	connector_id = atoi(strtok(NULL, "-"));
> +
> +	return connector_id;
> +}
> +
> +static bool is_dp_mst_output(igt_output_t *output, int i)
> +{
> +	drmModePropertyBlobPtr path_blob = NULL;
> +	uint64_t path_blob_id;
> +	drmModeConnector *connector = output->config.connector;
> +	struct kmstest_connector_config config;
> +	const char *encoder;
> +	int connector_id;
> +	static int prev_connector_id;
> +
> +	kmstest_get_connector_config(data.drm_fd, output->config.connector->connector_id, -1, &config);
> +	encoder = kmstest_encoder_type_str(config.encoder->encoder_type);
> +
> +	if (strcmp(encoder, "DP MST"))
> +		return false;
> +
> +	igt_assert(kmstest_get_property(data.drm_fd, connector->connector_id,
> +		   DRM_MODE_OBJECT_CONNECTOR, "PATH", NULL,
> +		   &path_blob_id, NULL));
> +
> +	igt_assert(path_blob = drmModeGetPropertyBlob(data.drm_fd, path_blob_id));
> +
> +	connector_id = parse_path_blob((char *) path_blob->data);
> +
> +	/* Check if all the MST outputs are in the same topology */
> +	if (i == 0) {
> +		prev_connector_id = connector_id;
> +	} else {
> +		if (connector_id != prev_connector_id)
> +			return false;
> +	}
> +
> +	drmModeFreePropertyBlob(path_blob);
> +
> +	return true;
> +}
> +
> +static void
> +test_content_protection_mst(int content_type)
> +{
> +	igt_display_t *display = &data.display;
> +	igt_output_t *output;
> +	int valid_outputs = 0, ret, count, max_pipe = 0;
> +	enum pipe pipe;
> +	igt_output_t *mst_output[IGT_MAX_PIPES];
> +
> +	for_each_connected_output(display, output) {
> +		if (!is_dp_mst_output(output, valid_outputs))
> +			continue;
> +
> +		if (!is_output_support_cp_capable(output, content_type))
> +			continue;
> +
> +		mst_output[valid_outputs] = output;
> +		valid_outputs++;
> +	}
> +
> +	igt_require_f(valid_outputs > 1, "No DP MST set up with >= 2 outputs found in a single topology\n");
> +
> +	for_each_pipe(display, pipe)
> +		max_pipe++;
> +
> +	if (valid_outputs > max_pipe)
> +		valid_outputs = max_pipe;
> +
> +	pipe = PIPE_A;
> +
> +	for (count = 0; count < valid_outputs; count++) {
> +		igt_assert_f(igt_pipe_connector_valid(pipe, mst_output[count]), "Output-pipe combination invalid\n");
> +
> +		prepare_modeset_on_mst_output(mst_output[count], pipe);
> +		pipe++;
> +	}
> +
> +	igt_display_commit2(display, COMMIT_ATOMIC);
> +
> +	for (count = 0; count < valid_outputs; count++) {
> +		igt_output_set_prop_value(mst_output[count], IGT_CONNECTOR_CONTENT_PROTECTION, CP_DESIRED);
> +
> +		if (output->props[IGT_CONNECTOR_HDCP_CONTENT_TYPE])
> +			igt_output_set_prop_value(mst_output[count], IGT_CONNECTOR_HDCP_CONTENT_TYPE, content_type);
> +	}
> +
> +	igt_display_commit2(display, COMMIT_ATOMIC);
> +
> +	for (count = 0; count < valid_outputs; count++) {
> +		igt_info("CP Prop check to be ENABLED %s\n", mst_output[count]->name);
		this is a debug log, in case we need it it should be some like "Test CP Prop to be ENABLED" .
> +		ret = wait_for_prop_value(mst_output[count], CP_ENABLED, KERNEL_AUTH_TIME_ALLOWED_MSEC);
> +		igt_assert_f(ret, "Content Protection not enabled output %s\n", mst_output[count]->name);
> +
> +		igt_kmsg("HDCP Prop is ENABLED %s\n", mst_output[count]->name);
		this is dmesg log for debugging not required any more.
> +
> +		if (data.cp_tests & CP_LIC)
> +			test_cp_lic(mst_output[count]);
> +	}
> +
> +	for (count = 0; count < valid_outputs; count++) {
> +		igt_info("CP Prop check to be ENABLED %s\n", mst_output[count]->name);
> +		ret = wait_for_prop_value(mst_output[count], CP_ENABLED, KERNEL_AUTH_TIME_ALLOWED_MSEC);
		this should be all possible combination of disabling CP property on one connector and extected to be ENABLED
		on another DP MST connector, currently it is not testing like disabling HDCP on second connecotr and expected
		to be enable on first connector.
> +		igt_assert_f(ret, "Content Protection not enabled output %s\n", mst_output[count]->name);
> +
> +		igt_info("CP Prop being UNDESIRED on %s\n", mst_output[count]->name);
		this should be debug log.
> +		test_cp_disable(mst_output[count], COMMIT_ATOMIC);
> +
> +		igt_kmsg("HDCP Prop is UNDESIRED %s\n", mst_output[count]->name);
		this is dmesg log for debugging not required any more.
Thanks ,
Anshuman
> +	}
> +}
> +
>  static void test_content_protection_cleanup(void)
>  {
>  	igt_display_t *display = &data.display;
> @@ -512,6 +709,7 @@ static void test_content_protection_cleanup(void)
>  			continue;
>  
>  		igt_info("CP Prop being UNDESIRED on %s\n", output->name);
> +		igt_kmsg("HDCP Prop being UNDESIRED %s\n", output->name);
		this is dmesg log for debugging not required any more.
>  		test_cp_disable(output, COMMIT_ATOMIC);
>  	}
>  }
> @@ -592,6 +790,28 @@ igt_main
>  		test_content_protection(COMMIT_ATOMIC, HDCP_CONTENT_TYPE_0);
>  	}
>  
> +	igt_describe("Test Content protection over DP MST");
> +	igt_subtest("dp-mst-type-0") {
> +		test_content_protection_mst(HDCP_CONTENT_TYPE_0);
> +	}
> +
> +	igt_describe("Test Content protection over DP MST with LIC");
> +	igt_subtest("dp-mst-lic-type-0") {
> +		data.cp_tests = CP_LIC;
> +		test_content_protection_mst(HDCP_CONTENT_TYPE_0);
> +	}
> +
> +	igt_describe("Test Content protection over DP MST");
> +	igt_subtest("dp-mst-type-1") {
> +		test_content_protection_mst(HDCP_CONTENT_TYPE_1);
> +	}
> +
> +	igt_describe("Test Content protection over DP MST with LIC");
> +	igt_subtest("dp-mst-lic-type-1") {
> +		data.cp_tests = CP_LIC;
> +		test_content_protection_mst(HDCP_CONTENT_TYPE_1);
> +	}
> +
>  	igt_fixture {
>  		test_content_protection_cleanup();
>  		igt_display_fini(&data.display);
> -- 
> 2.22.0
> 


More information about the igt-dev mailing list