diff mbox

[i-g-t,1/2] lib: add functions to change connector states

Message ID 1400506928-12775-2-git-send-email-thomas.wood@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thomas Wood May 19, 2014, 1:42 p.m. UTC
Add a function to force a particular state on a connector and a
convenience function to find and set the state on the VGA connector.

Signed-off-by: Thomas Wood <thomas.wood@intel.com>
---
 lib/igt_kms.c               | 78 ++++++++++++++++++++++++++++++++++++++++
 lib/igt_kms.h               | 12 +++++++
 tests/Makefile.sources      |  1 +
 tests/kms_force_connector.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 178 insertions(+)
 create mode 100644 tests/kms_force_connector.c

Comments

Daniel Vetter May 19, 2014, 2:28 p.m. UTC | #1
On Mon, May 19, 2014 at 02:42:07PM +0100, Thomas Wood wrote:
> Add a function to force a particular state on a connector and a
> convenience function to find and set the state on the VGA connector.
> 
> Signed-off-by: Thomas Wood <thomas.wood@intel.com>
> ---
>  lib/igt_kms.c               | 78 ++++++++++++++++++++++++++++++++++++++++
>  lib/igt_kms.h               | 12 +++++++
>  tests/Makefile.sources      |  1 +
>  tests/kms_force_connector.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 178 insertions(+)
>  create mode 100644 tests/kms_force_connector.c
> 
> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> index d00250d..90c3e56 100644
> --- a/lib/igt_kms.c
> +++ b/lib/igt_kms.c
> @@ -384,6 +384,61 @@ err1:
>  	return -1;
>  }
>  
> +static int get_card_number(int fd)
> +{
> +	struct stat buf;
> +
> +	/* find the minor number of the device */
> +	fstat(fd, &buf);
> +
> +	return minor(buf.st_rdev);
> +}
> +
> +/**
> + * kmstest_force_connector:
> + * @fd: drm file descriptor
> + * @connector: connector
> + * @state: state to force on @connector
> + *
> + * Force the specified state on the specified connector.
> + */
> +void kmstest_force_connector(int drm_fd, drmModeConnector *connector, enum
> +			     force_connector state)

Hm, for the interface I've thought more about
kmsttest_force_connector(drm_fd, connector, edid) since most often we
don't just want to force the state, but set a specific EDID (for a
high-res mode or something similar).

> +{
> +	char *path;
> +	const char *value;
> +	int sysfs_fd, ret;
> +
> +	switch (state) {
> +	case FORCE_CONNECTOR_UNSPECIFIED:
> +		value = "unspecified";
> +		break;
> +	case FORCE_CONNECTOR_ON:
> +		value = "on";
> +		break;
> +	case FORCE_CONNECTOR_DIGITAL:
> +		value = "digital";
> +		break;
> +	case FORCE_CONNECTOR_OFF:
> +		value = "off";
> +		break;
> +	}
> +
> +	asprintf(&path, "/sys/class/drm/card%d-%s-%d/force",
> +		 get_card_number(drm_fd),
> +		 kmstest_connector_type_str(connector->connector_type),
> +		 connector->connector_type_id);
> +	sysfs_fd = open(path, O_WRONLY | O_TRUNC);
> +	free(path);
> +
> +	igt_assert(sysfs_fd != -1);
> +
> +	ret = write(sysfs_fd, value, strlen(value) + 1);
> +	close(sysfs_fd);
> +
> +	igt_assert(ret != -1);
> +}

We need an exit handler to clean up this mess again ;-)

> +
>  void kmstest_free_connector_config(struct kmstest_connector_config *config)
>  {
>  	drmModeFreeCrtc(config->crtc);
> @@ -1047,3 +1102,26 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
>  
>  	igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0);
>  }
> +
> +void igt_set_vga_connector_state(int drm_fd, enum force_connector state)

Hm, for the higher-level library I've thought we'd just force everything
we reaosonable can, so I'd drop the vga here and also the state. So maybe
just igt_enable_fake_connectors(drm_fd, flags);

> +{
> +	drmModeRes *res;
> +	drmModeConnector *c;
> +
> +	res = drmModeGetResources(drm_fd);
> +
> +	/* find the vga connector */
> +	for (int i = 0; i < res->count_connectors; i++) {
> +
> +		c = drmModeGetConnector(drm_fd, res->connectors[i]);
> +
> +		if (c->connector_type == DRM_MODE_CONNECTOR_VGA)
> +			break;
> +
> +		drmModeFreeConnector(c);
> +	}
> +
> +	kmstest_force_connector(drm_fd, c, state);
> +
> +	drmModeFreeConnector(c);
> +}
> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> index 8e80d4b..71f6831 100644
> --- a/lib/igt_kms.h
> +++ b/lib/igt_kms.h
> @@ -75,11 +75,20 @@ struct kmstest_connector_config {
>  	int pipe;
>  };
>  
> +enum force_connector {
> +	FORCE_CONNECTOR_UNSPECIFIED,
> +	FORCE_CONNECTOR_ON,
> +	FORCE_CONNECTOR_DIGITAL,
> +	FORCE_CONNECTOR_OFF
> +};
> +
>  int kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
>  				      drmModeModeInfo *mode);
>  int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
>  				 unsigned long crtc_idx_mask,
>  				 struct kmstest_connector_config *config);
> +void kmstest_force_connector(int fd, drmModeConnector *connector,
> +			     enum force_connector state);
>  void kmstest_free_connector_config(struct kmstest_connector_config *config);
>  
>  void kmstest_dump_mode(drmModeModeInfo *mode);
> @@ -175,5 +184,8 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
>  
>  #define IGT_FIXED(i,f)	((i) << 16 | (f))
>  
> +
> +void igt_set_vga_connector_state(int drm_fd, enum force_connector state);
> +
>  #endif /* __IGT_KMS_H__ */
>  
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index fbf63e9..eff0124 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -134,6 +134,7 @@ TESTS_progs = \
>  	gen3_render_tiledx_blits \
>  	gen3_render_tiledy_blits \
>  	gen7_forcewake_mt \
> +	kms_force_connector \
>  	kms_sink_crc_basic \
>  	pm_psr \
>  	pm_rc6_residency \
> diff --git a/tests/kms_force_connector.c b/tests/kms_force_connector.c
> new file mode 100644
> index 0000000..b2659ae
> --- /dev/null
> +++ b/tests/kms_force_connector.c
> @@ -0,0 +1,87 @@
> +/*
> + * Copyright © 2014 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "igt_core.h"
> +#include "igt_kms.h"
> +#include "drmtest.h"
> +
> +int
> +main (int argc, char **argv)
> +{
> +	/* force the VGA & HDMI output and test it worked */
> +	int drm_fd;
> +	drmModeRes *res;
> +	drmModeConnector *c, *temp;
> +
> +	igt_simple_init();
> +
> +	drm_fd = drm_open_any();
> +	res = drmModeGetResources(drm_fd);
> +
> +	/* find the vga connector */
> +	for (int i = 0; i < res->count_connectors; i++) {
> +
> +		c = drmModeGetConnector(drm_fd, res->connectors[i]);
> +
> +		if (c->connector_type == DRM_MODE_CONNECTOR_LVDS)
> +			break;
> +
> +		drmModeFreeConnector(c);
> +	}
> +
> +	/* force the connector state and check the reported value */
> +	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_ON);
> +	temp = drmModeGetConnector(drm_fd, c->connector_id);
> +	igt_assert(temp->connection == DRM_MODE_CONNECTED);
> +	igt_assert(temp->count_modes > 0);
> +	drmModeFreeConnector(temp);
> +
> +	/* attempt to use the display */
> +	{
> +		igt_display_t display;
> +
> +		igt_set_vt_graphics_mode();
> +
> +		igt_display_init(&display, drm_fd);
> +		igt_display_commit(&display);
> +	}
> +
> +
> +	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_OFF);
> +	temp = drmModeGetConnector(drm_fd, c->connector_id);
> +	igt_assert(temp->connection == DRM_MODE_DISCONNECTED);
> +	igt_assert(temp->count_modes = 0);
> +	drmModeFreeConnector(temp);
> +
> +
> +	/* check that the previous state is restored */
> +	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_UNSPECIFIED);
> +	temp = drmModeGetConnector(drm_fd, c->connector_id);
> +	igt_assert(temp->connection == c->connection);
> +	drmModeFreeConnector(temp);
> +
> +	drmModeFreeConnector(c);
> +
> +	igt_success();
> +}
> -- 
> 1.9.0
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Thomas Wood May 19, 2014, 2:57 p.m. UTC | #2
On 19 May 2014 15:28, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Mon, May 19, 2014 at 02:42:07PM +0100, Thomas Wood wrote:
>> Add a function to force a particular state on a connector and a
>> convenience function to find and set the state on the VGA connector.
>>
>> Signed-off-by: Thomas Wood <thomas.wood@intel.com>
>> ---
>>  lib/igt_kms.c               | 78 ++++++++++++++++++++++++++++++++++++++++
>>  lib/igt_kms.h               | 12 +++++++
>>  tests/Makefile.sources      |  1 +
>>  tests/kms_force_connector.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
>>  4 files changed, 178 insertions(+)
>>  create mode 100644 tests/kms_force_connector.c
>>
>> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
>> index d00250d..90c3e56 100644
>> --- a/lib/igt_kms.c
>> +++ b/lib/igt_kms.c
>> @@ -384,6 +384,61 @@ err1:
>>       return -1;
>>  }
>>
>> +static int get_card_number(int fd)
>> +{
>> +     struct stat buf;
>> +
>> +     /* find the minor number of the device */
>> +     fstat(fd, &buf);
>> +
>> +     return minor(buf.st_rdev);
>> +}
>> +
>> +/**
>> + * kmstest_force_connector:
>> + * @fd: drm file descriptor
>> + * @connector: connector
>> + * @state: state to force on @connector
>> + *
>> + * Force the specified state on the specified connector.
>> + */
>> +void kmstest_force_connector(int drm_fd, drmModeConnector *connector, enum
>> +                          force_connector state)
>
> Hm, for the interface I've thought more about
> kmsttest_force_connector(drm_fd, connector, edid) since most often we
> don't just want to force the state, but set a specific EDID (for a
> high-res mode or something similar).

Many tests don't need a specific mode, so the default ones are fine.
Obviously in those cases they may just be able to pass NULL for the
edid in the prototype you suggested, but the main thing here is to be
able to enable the connector and use it. Another consideration when
setting edid would be to prevent arbitrary edid values being set on a
connector that actually has a display connected.

>
>> +{
>> +     char *path;
>> +     const char *value;
>> +     int sysfs_fd, ret;
>> +
>> +     switch (state) {
>> +     case FORCE_CONNECTOR_UNSPECIFIED:
>> +             value = "unspecified";
>> +             break;
>> +     case FORCE_CONNECTOR_ON:
>> +             value = "on";
>> +             break;
>> +     case FORCE_CONNECTOR_DIGITAL:
>> +             value = "digital";
>> +             break;
>> +     case FORCE_CONNECTOR_OFF:
>> +             value = "off";
>> +             break;
>> +     }
>> +
>> +     asprintf(&path, "/sys/class/drm/card%d-%s-%d/force",
>> +              get_card_number(drm_fd),
>> +              kmstest_connector_type_str(connector->connector_type),
>> +              connector->connector_type_id);
>> +     sysfs_fd = open(path, O_WRONLY | O_TRUNC);
>> +     free(path);
>> +
>> +     igt_assert(sysfs_fd != -1);
>> +
>> +     ret = write(sysfs_fd, value, strlen(value) + 1);
>> +     close(sysfs_fd);
>> +
>> +     igt_assert(ret != -1);
>> +}
>
> We need an exit handler to clean up this mess again ;-)
>
>> +
>>  void kmstest_free_connector_config(struct kmstest_connector_config *config)
>>  {
>>       drmModeFreeCrtc(config->crtc);
>> @@ -1047,3 +1102,26 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
>>
>>       igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0);
>>  }
>> +
>> +void igt_set_vga_connector_state(int drm_fd, enum force_connector state)
>
> Hm, for the higher-level library I've thought we'd just force everything
> we reaosonable can, so I'd drop the vga here and also the state. So maybe
> just igt_enable_fake_connectors(drm_fd, flags);

How would the state be reset? Using an exit handler?

>
>> +{
>> +     drmModeRes *res;
>> +     drmModeConnector *c;
>> +
>> +     res = drmModeGetResources(drm_fd);
>> +
>> +     /* find the vga connector */
>> +     for (int i = 0; i < res->count_connectors; i++) {
>> +
>> +             c = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +
>> +             if (c->connector_type == DRM_MODE_CONNECTOR_VGA)
>> +                     break;
>> +
>> +             drmModeFreeConnector(c);
>> +     }
>> +
>> +     kmstest_force_connector(drm_fd, c, state);
>> +
>> +     drmModeFreeConnector(c);
>> +}
>> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
>> index 8e80d4b..71f6831 100644
>> --- a/lib/igt_kms.h
>> +++ b/lib/igt_kms.h
>> @@ -75,11 +75,20 @@ struct kmstest_connector_config {
>>       int pipe;
>>  };
>>
>> +enum force_connector {
>> +     FORCE_CONNECTOR_UNSPECIFIED,
>> +     FORCE_CONNECTOR_ON,
>> +     FORCE_CONNECTOR_DIGITAL,
>> +     FORCE_CONNECTOR_OFF
>> +};
>> +
>>  int kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
>>                                     drmModeModeInfo *mode);
>>  int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
>>                                unsigned long crtc_idx_mask,
>>                                struct kmstest_connector_config *config);
>> +void kmstest_force_connector(int fd, drmModeConnector *connector,
>> +                          enum force_connector state);
>>  void kmstest_free_connector_config(struct kmstest_connector_config *config);
>>
>>  void kmstest_dump_mode(drmModeModeInfo *mode);
>> @@ -175,5 +184,8 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
>>
>>  #define IGT_FIXED(i,f)       ((i) << 16 | (f))
>>
>> +
>> +void igt_set_vga_connector_state(int drm_fd, enum force_connector state);
>> +
>>  #endif /* __IGT_KMS_H__ */
>>
>> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
>> index fbf63e9..eff0124 100644
>> --- a/tests/Makefile.sources
>> +++ b/tests/Makefile.sources
>> @@ -134,6 +134,7 @@ TESTS_progs = \
>>       gen3_render_tiledx_blits \
>>       gen3_render_tiledy_blits \
>>       gen7_forcewake_mt \
>> +     kms_force_connector \
>>       kms_sink_crc_basic \
>>       pm_psr \
>>       pm_rc6_residency \
>> diff --git a/tests/kms_force_connector.c b/tests/kms_force_connector.c
>> new file mode 100644
>> index 0000000..b2659ae
>> --- /dev/null
>> +++ b/tests/kms_force_connector.c
>> @@ -0,0 +1,87 @@
>> +/*
>> + * Copyright © 2014 Intel Corporation
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a
>> + * copy of this software and associated documentation files (the "Software"),
>> + * to deal in the Software without restriction, including without limitation
>> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> + * and/or sell copies of the Software, and to permit persons to whom the
>> + * Software is furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice (including the next
>> + * paragraph) shall be included in all copies or substantial portions of the
>> + * Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
>> + * IN THE SOFTWARE.
>> + *
>> + */
>> +
>> +#include "igt_core.h"
>> +#include "igt_kms.h"
>> +#include "drmtest.h"
>> +
>> +int
>> +main (int argc, char **argv)
>> +{
>> +     /* force the VGA & HDMI output and test it worked */
>> +     int drm_fd;
>> +     drmModeRes *res;
>> +     drmModeConnector *c, *temp;
>> +
>> +     igt_simple_init();
>> +
>> +     drm_fd = drm_open_any();
>> +     res = drmModeGetResources(drm_fd);
>> +
>> +     /* find the vga connector */
>> +     for (int i = 0; i < res->count_connectors; i++) {
>> +
>> +             c = drmModeGetConnector(drm_fd, res->connectors[i]);
>> +
>> +             if (c->connector_type == DRM_MODE_CONNECTOR_LVDS)
>> +                     break;
>> +
>> +             drmModeFreeConnector(c);
>> +     }
>> +
>> +     /* force the connector state and check the reported value */
>> +     kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_ON);
>> +     temp = drmModeGetConnector(drm_fd, c->connector_id);
>> +     igt_assert(temp->connection == DRM_MODE_CONNECTED);
>> +     igt_assert(temp->count_modes > 0);
>> +     drmModeFreeConnector(temp);
>> +
>> +     /* attempt to use the display */
>> +     {
>> +             igt_display_t display;
>> +
>> +             igt_set_vt_graphics_mode();
>> +
>> +             igt_display_init(&display, drm_fd);
>> +             igt_display_commit(&display);
>> +     }
>> +
>> +
>> +     kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_OFF);
>> +     temp = drmModeGetConnector(drm_fd, c->connector_id);
>> +     igt_assert(temp->connection == DRM_MODE_DISCONNECTED);
>> +     igt_assert(temp->count_modes = 0);
>> +     drmModeFreeConnector(temp);
>> +
>> +
>> +     /* check that the previous state is restored */
>> +     kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_UNSPECIFIED);
>> +     temp = drmModeGetConnector(drm_fd, c->connector_id);
>> +     igt_assert(temp->connection == c->connection);
>> +     drmModeFreeConnector(temp);
>> +
>> +     drmModeFreeConnector(c);
>> +
>> +     igt_success();
>> +}
>> --
>> 1.9.0
>>
>> _______________________________________________
>> Intel-gfx mailing list
>> Intel-gfx@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Daniel Vetter May 19, 2014, 3:16 p.m. UTC | #3
On Mon, May 19, 2014 at 03:57:36PM +0100, Thomas Wood wrote:
> On 19 May 2014 15:28, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Mon, May 19, 2014 at 02:42:07PM +0100, Thomas Wood wrote:
> >> Add a function to force a particular state on a connector and a
> >> convenience function to find and set the state on the VGA connector.
> >>
> >> Signed-off-by: Thomas Wood <thomas.wood@intel.com>
> >> ---
> >>  lib/igt_kms.c               | 78 ++++++++++++++++++++++++++++++++++++++++
> >>  lib/igt_kms.h               | 12 +++++++
> >>  tests/Makefile.sources      |  1 +
> >>  tests/kms_force_connector.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
> >>  4 files changed, 178 insertions(+)
> >>  create mode 100644 tests/kms_force_connector.c
> >>
> >> diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> >> index d00250d..90c3e56 100644
> >> --- a/lib/igt_kms.c
> >> +++ b/lib/igt_kms.c
> >> @@ -384,6 +384,61 @@ err1:
> >>       return -1;
> >>  }
> >>
> >> +static int get_card_number(int fd)
> >> +{
> >> +     struct stat buf;
> >> +
> >> +     /* find the minor number of the device */
> >> +     fstat(fd, &buf);
> >> +
> >> +     return minor(buf.st_rdev);
> >> +}
> >> +
> >> +/**
> >> + * kmstest_force_connector:
> >> + * @fd: drm file descriptor
> >> + * @connector: connector
> >> + * @state: state to force on @connector
> >> + *
> >> + * Force the specified state on the specified connector.
> >> + */
> >> +void kmstest_force_connector(int drm_fd, drmModeConnector *connector, enum
> >> +                          force_connector state)
> >
> > Hm, for the interface I've thought more about
> > kmsttest_force_connector(drm_fd, connector, edid) since most often we
> > don't just want to force the state, but set a specific EDID (for a
> > high-res mode or something similar).
> 
> Many tests don't need a specific mode, so the default ones are fine.
> Obviously in those cases they may just be able to pass NULL for the
> edid in the prototype you suggested, but the main thing here is to be
> able to enable the connector and use it. Another consideration when
> setting edid would be to prevent arbitrary edid values being set on a
> connector that actually has a display connected.

Yeah, sanity checks are missing, too. Wrt the edid I've thought we could
just add some random 1080p panel with a pile of modes to keep things
interesting. 1024x756 is kinda low-res nowadays, so not really that
interesting for testing.

Same with hdmi/dp (if we get around to that): Imo the default injection
should be a really big panel so that we have lots of upscaled modes and
good chances to stress-test the watermark code a bit.
> 
> >
> >> +{
> >> +     char *path;
> >> +     const char *value;
> >> +     int sysfs_fd, ret;
> >> +
> >> +     switch (state) {
> >> +     case FORCE_CONNECTOR_UNSPECIFIED:
> >> +             value = "unspecified";
> >> +             break;
> >> +     case FORCE_CONNECTOR_ON:
> >> +             value = "on";
> >> +             break;
> >> +     case FORCE_CONNECTOR_DIGITAL:
> >> +             value = "digital";
> >> +             break;
> >> +     case FORCE_CONNECTOR_OFF:
> >> +             value = "off";
> >> +             break;
> >> +     }
> >> +
> >> +     asprintf(&path, "/sys/class/drm/card%d-%s-%d/force",
> >> +              get_card_number(drm_fd),
> >> +              kmstest_connector_type_str(connector->connector_type),
> >> +              connector->connector_type_id);
> >> +     sysfs_fd = open(path, O_WRONLY | O_TRUNC);
> >> +     free(path);
> >> +
> >> +     igt_assert(sysfs_fd != -1);
> >> +
> >> +     ret = write(sysfs_fd, value, strlen(value) + 1);
> >> +     close(sysfs_fd);
> >> +
> >> +     igt_assert(ret != -1);
> >> +}
> >
> > We need an exit handler to clean up this mess again ;-)
> >
> >> +
> >>  void kmstest_free_connector_config(struct kmstest_connector_config *config)
> >>  {
> >>       drmModeFreeCrtc(config->crtc);
> >> @@ -1047,3 +1102,26 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
> >>
> >>       igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0);
> >>  }
> >> +
> >> +void igt_set_vga_connector_state(int drm_fd, enum force_connector state)
> >
> > Hm, for the higher-level library I've thought we'd just force everything
> > we reaosonable can, so I'd drop the vga here and also the state. So maybe
> > just igt_enable_fake_connectors(drm_fd, flags);
> 
> How would the state be reset? Using an exit handler?

Yeah, if the low-level code has some bookmarking + cleanup handlers the
high-level doesn't need to do much. Maybe we could expose a general reset
function, which could be used by tests to reset injection state if they
have special needs.
-Daniel
diff mbox

Patch

diff --git a/lib/igt_kms.c b/lib/igt_kms.c
index d00250d..90c3e56 100644
--- a/lib/igt_kms.c
+++ b/lib/igt_kms.c
@@ -384,6 +384,61 @@  err1:
 	return -1;
 }
 
+static int get_card_number(int fd)
+{
+	struct stat buf;
+
+	/* find the minor number of the device */
+	fstat(fd, &buf);
+
+	return minor(buf.st_rdev);
+}
+
+/**
+ * kmstest_force_connector:
+ * @fd: drm file descriptor
+ * @connector: connector
+ * @state: state to force on @connector
+ *
+ * Force the specified state on the specified connector.
+ */
+void kmstest_force_connector(int drm_fd, drmModeConnector *connector, enum
+			     force_connector state)
+{
+	char *path;
+	const char *value;
+	int sysfs_fd, ret;
+
+	switch (state) {
+	case FORCE_CONNECTOR_UNSPECIFIED:
+		value = "unspecified";
+		break;
+	case FORCE_CONNECTOR_ON:
+		value = "on";
+		break;
+	case FORCE_CONNECTOR_DIGITAL:
+		value = "digital";
+		break;
+	case FORCE_CONNECTOR_OFF:
+		value = "off";
+		break;
+	}
+
+	asprintf(&path, "/sys/class/drm/card%d-%s-%d/force",
+		 get_card_number(drm_fd),
+		 kmstest_connector_type_str(connector->connector_type),
+		 connector->connector_type_id);
+	sysfs_fd = open(path, O_WRONLY | O_TRUNC);
+	free(path);
+
+	igt_assert(sysfs_fd != -1);
+
+	ret = write(sysfs_fd, value, strlen(value) + 1);
+	close(sysfs_fd);
+
+	igt_assert(ret != -1);
+}
+
 void kmstest_free_connector_config(struct kmstest_connector_config *config)
 {
 	drmModeFreeCrtc(config->crtc);
@@ -1047,3 +1102,26 @@  void igt_wait_for_vblank(int drm_fd, enum pipe pipe)
 
 	igt_assert(drmWaitVBlank(drm_fd, &wait_vbl) == 0);
 }
+
+void igt_set_vga_connector_state(int drm_fd, enum force_connector state)
+{
+	drmModeRes *res;
+	drmModeConnector *c;
+
+	res = drmModeGetResources(drm_fd);
+
+	/* find the vga connector */
+	for (int i = 0; i < res->count_connectors; i++) {
+
+		c = drmModeGetConnector(drm_fd, res->connectors[i]);
+
+		if (c->connector_type == DRM_MODE_CONNECTOR_VGA)
+			break;
+
+		drmModeFreeConnector(c);
+	}
+
+	kmstest_force_connector(drm_fd, c, state);
+
+	drmModeFreeConnector(c);
+}
diff --git a/lib/igt_kms.h b/lib/igt_kms.h
index 8e80d4b..71f6831 100644
--- a/lib/igt_kms.h
+++ b/lib/igt_kms.h
@@ -75,11 +75,20 @@  struct kmstest_connector_config {
 	int pipe;
 };
 
+enum force_connector {
+	FORCE_CONNECTOR_UNSPECIFIED,
+	FORCE_CONNECTOR_ON,
+	FORCE_CONNECTOR_DIGITAL,
+	FORCE_CONNECTOR_OFF
+};
+
 int kmstest_get_connector_default_mode(int drm_fd, drmModeConnector *connector,
 				      drmModeModeInfo *mode);
 int kmstest_get_connector_config(int drm_fd, uint32_t connector_id,
 				 unsigned long crtc_idx_mask,
 				 struct kmstest_connector_config *config);
+void kmstest_force_connector(int fd, drmModeConnector *connector,
+			     enum force_connector state);
 void kmstest_free_connector_config(struct kmstest_connector_config *config);
 
 void kmstest_dump_mode(drmModeModeInfo *mode);
@@ -175,5 +184,8 @@  void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
 
 #define IGT_FIXED(i,f)	((i) << 16 | (f))
 
+
+void igt_set_vga_connector_state(int drm_fd, enum force_connector state);
+
 #endif /* __IGT_KMS_H__ */
 
diff --git a/tests/Makefile.sources b/tests/Makefile.sources
index fbf63e9..eff0124 100644
--- a/tests/Makefile.sources
+++ b/tests/Makefile.sources
@@ -134,6 +134,7 @@  TESTS_progs = \
 	gen3_render_tiledx_blits \
 	gen3_render_tiledy_blits \
 	gen7_forcewake_mt \
+	kms_force_connector \
 	kms_sink_crc_basic \
 	pm_psr \
 	pm_rc6_residency \
diff --git a/tests/kms_force_connector.c b/tests/kms_force_connector.c
new file mode 100644
index 0000000..b2659ae
--- /dev/null
+++ b/tests/kms_force_connector.c
@@ -0,0 +1,87 @@ 
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#include "igt_core.h"
+#include "igt_kms.h"
+#include "drmtest.h"
+
+int
+main (int argc, char **argv)
+{
+	/* force the VGA & HDMI output and test it worked */
+	int drm_fd;
+	drmModeRes *res;
+	drmModeConnector *c, *temp;
+
+	igt_simple_init();
+
+	drm_fd = drm_open_any();
+	res = drmModeGetResources(drm_fd);
+
+	/* find the vga connector */
+	for (int i = 0; i < res->count_connectors; i++) {
+
+		c = drmModeGetConnector(drm_fd, res->connectors[i]);
+
+		if (c->connector_type == DRM_MODE_CONNECTOR_LVDS)
+			break;
+
+		drmModeFreeConnector(c);
+	}
+
+	/* force the connector state and check the reported value */
+	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_ON);
+	temp = drmModeGetConnector(drm_fd, c->connector_id);
+	igt_assert(temp->connection == DRM_MODE_CONNECTED);
+	igt_assert(temp->count_modes > 0);
+	drmModeFreeConnector(temp);
+
+	/* attempt to use the display */
+	{
+		igt_display_t display;
+
+		igt_set_vt_graphics_mode();
+
+		igt_display_init(&display, drm_fd);
+		igt_display_commit(&display);
+	}
+
+
+	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_OFF);
+	temp = drmModeGetConnector(drm_fd, c->connector_id);
+	igt_assert(temp->connection == DRM_MODE_DISCONNECTED);
+	igt_assert(temp->count_modes = 0);
+	drmModeFreeConnector(temp);
+
+
+	/* check that the previous state is restored */
+	kmstest_force_connector(drm_fd, c, FORCE_CONNECTOR_UNSPECIFIED);
+	temp = drmModeGetConnector(drm_fd, c->connector_id);
+	igt_assert(temp->connection == c->connection);
+	drmModeFreeConnector(temp);
+
+	drmModeFreeConnector(c);
+
+	igt_success();
+}