diff mbox

[i-g-t,v3] tools: Add intel_dp_compliance for DisplayPort 1.2 compliance automation

Message ID C56C55B681623645A065C9EE352337D6110D5329@ORSMSX109.amr.corp.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Dhinakaran Pandiyan Dec. 23, 2016, 7:47 a.m. UTC
I have addressed review comments that Petri, Jim had for this patch along with making some small changes for error handling. The functionality is mostly unchanged from Manasi's version.

-DK

Comments

Petri Latvala Jan. 11, 2017, 1:44 p.m. UTC | #1
Hi

The copyright statements still need the year
corrected. intel_dp_compliance needs to be added to tools/.gitignore

Some new comments also:

- Why do some of the prints have \r\n?
- Building intel_dp_compliance should actually be made conditional upon HAVE_UDEV



--
Petri Latvala



On Fri, Dec 23, 2016 at 09:47:48AM +0200, Pandiyan, Dhinakaran wrote:
> I have addressed review comments that Petri, Jim had for this patch along with making some small changes for error handling. The functionality is mostly unchanged from Manasi's version.
> 
> -DK
> ________________________________________
> From: Pandiyan, Dhinakaran
> Sent: Thursday, December 22, 2016 11:41 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: jim.bride@linux.intel.com; Navare, Manasi D; Latvala, Petri; Vlad, Marius C; Daniel Vetter; Pandiyan, Dhinakaran
> Subject: [PATCH i-g-t v3] tools: Add intel_dp_compliance for DisplayPort 1.2 compliance automation
> 
> From: "Navare, Manasi D" <manasi.d.navare@intel.com>
> 
> This is the userspace component of the Displayport Compliance
> testing software required for compliance testing of the I915
> Display Port driver. This must be running in order to successfully
> complete Display Port compliance testing. This app and the kernel
> code that accompanies it has been written to satify the requirements
> of the Displayport Link CTS 1.2 rev1.1 specification from VESA.
> Note that this application does not support eDP compliance testing.
> This utility has an automation support for the Link training tests
> (4.3.1.1. - 4.3.2.3), EDID tests (4.2.2.3
> - 4.2.2.6) and Video Pattern generation tests (4.3.3.1) from CTS
> specification 1.2 Rev 1.1.
> 
> This tool has the support for responding to the hotplug uevents
> sent by compliance testting unit after each test.
> 
> The Linux DUT running this utility must be in text (console) mode
> and cannot have any other display manager running. Since this uses
> sysfs nodes for kernel interaction, this utility should be run as
> Root. Once this user application is up and running, waiting for
> test requests, the test appliance software on the windows host
> can now be used to execute the compliance tests.
> 
> This app is based on some prior work done in April 2015 (by
> Todd Previte <tprevite@gmail.com>)
> 
> v2:
> * Add mode unset on hotplug uevent on disconnect (Manasi Navare)
> 
> v3:
> Made capitalization consistent
> Reduced line lengths
> Added return value checks
> Changed how GLib is linked
> Fixed build warnings
> 
> Cc: Petri Latvala <petri.latvala@intel.com>
> Cc: Marius Vlad <marius.c.vlad@intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> ---
>  tools/Makefile.am                   |    1 +
>  tools/Makefile.sources              |    7 +
>  tools/intel_dp_compliance.c         | 1104 +++++++++++++++++++++++++++++++++++
>  tools/intel_dp_compliance.h         |   35 ++
>  tools/intel_dp_compliance_hotplug.c |  123 ++++
>  5 files changed, 1270 insertions(+)
>  create mode 100644 tools/intel_dp_compliance.c
>  create mode 100644 tools/intel_dp_compliance.h
>  create mode 100644 tools/intel_dp_compliance_hotplug.c
> 
> diff --git a/tools/Makefile.am b/tools/Makefile.am
> index 18f86f6..bd8f512 100644
> --- a/tools/Makefile.am
> +++ b/tools/Makefile.am
> @@ -16,6 +16,7 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \
>  LDADD = $(top_builddir)/lib/libintel_tools.la
>  AM_LDFLAGS = -Wl,--as-needed
> 
> +intel_dp_compliance_LDADD = $(top_builddir)/lib/libintel_tools.la $(GLIB_LIBS)
> 
>  # aubdumper
> 
> diff --git a/tools/Makefile.sources b/tools/Makefile.sources
> index e2451ea..e8ce891 100644
> --- a/tools/Makefile.sources
> +++ b/tools/Makefile.sources
> @@ -13,6 +13,7 @@ tools_prog_lists =            \
>         intel_bios_reader       \
>         intel_display_crc       \
>         intel_display_poller    \
> +       intel_dp_compliance     \
>         intel_forcewaked        \
>         intel_gpu_frequency     \
>         intel_firmware_decode   \
> @@ -56,3 +57,9 @@ intel_l3_parity_SOURCES =     \
>         intel_l3_parity.h       \
>         intel_l3_udev_listener.c
> 
> +intel_dp_compliance_SOURCES = \
> +        intel_dp_compliance.c \
> +        intel_dp_compliance.h \
> +        intel_dp_compliance_hotplug.c \
> +        $(NULL)
> +
> diff --git a/tools/intel_dp_compliance.c b/tools/intel_dp_compliance.c
> new file mode 100644
> index 0000000..df1ca10
> --- /dev/null
> +++ b/tools/intel_dp_compliance.c
> @@ -0,0 +1,1104 @@
> +/*
> + * 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.
> + *
> + * Displayport Compliance Testing Application
> + *
> + * This is the userspace component of the Displayport Compliance testing
> + * software required for compliance testing of the I915 Display Port driver.
> + * This must be running in order to successfully complete Display Port
> + * compliance testing. This app and the kernel code that accompanies it has been
> + * written to satify the requirements of the Displayport Link CTS 1.2 rev1.1
> + * specification from VESA. Note that this application does not support eDP
> + * compliance testing.
> + *
> + * Compliance Testing requires several components:
> + *   - A kernel build that contains the patch set for DP compliance support
> + *   - A Displayport Compliance Testing appliance such as Unigraf-DPR120
> + *   - This user application
> + *   - A windows host machine to run the DPR test software
> + *   - Root access on the DUT due to the use of sysfs utility
> + *
> + * Test Setup:
> + * It is strongly recommended that the windows host, test appliance and DUT
> + * be freshly restarted before any testing begins to ensure that any previous
> + * configurations and settings will not interfere with test process. Refer to
> + * the test appliance documentation for setup, software installation and
> + * operation specific to that device.
> + *
> + * The Linux DUT must be in text (console) mode and cannot have any other
> + * display manager running. You must be logged in as root to run this user app.
> + * Once the user application is up and running, waiting for test requests, the
> + * software on the windows host can now be used to execute the compliance tests.
> + *
> + * This userspace application supports following tests from the DP CTS Spec
> + * Rev 1.1:
> + *   - Link Training Tests: Supports tests 4.3.1.1 to 4.3.2.3
> + *   - EDID Tests: Supports EDID read (4.2.2.3),EDID Read failure and corruption
> + *     detection tests (4.2.2.4, 4.2.2.5, 4.2.2.6)
> + *   - Video Pattern generation tests: This supports only the 24 and 18bpp color
> + *     ramp test pattern (4.3.3.1).
> + *
> + * Connections (required):
> + *   - Test Appliance connected to the external Displayport connector on the DUT
> + *   - Test Appliance Monitor Out connected to Displayport connector on the
> + * monitor
> + *   - Test appliance connected to the Windows Host via USB
> + *
> + * Debugfs Files:
> + * The file root for all  the debugfs file:
> + * /sys/kernel/debug/dri/0/
> + *
> + * The specific files are as follows:
> + *
> + * i915_dp_test_active
> + * A simple flag that indicates whether or not compliance testing is currently
> + * active in the kernel. This flag is polled by userspace and once set, invokes
> + * the test handler in the user app. This flag is set by the test handler in the
> + * kernel after reading the registers requested by the test appliance.
> + *
> + * i915_dp_test_data
> + * Test data is used by the kernel to pass parameters to the user app. Eg: In
> + * case of EDID tests, the data that is delivered to the userspace is the video
> + * mode to be set for the test.
> + * In case of video pattern test, the data that is delivered to the userspace is
> + * the width and height of the test pattern and the bits per color value.
> + *
> + * i915_dp_test_type
> + * The test type variable instructs the user app as to what the requested test
> + * was from the sink device. These values defined at the top of the application's
> + * main implementation file must be kept in sync with the values defined in the
> + * kernel's drm_dp_helper.h file.
> + * This app is based on some prior work submitted in April 2015 by Todd Previte
> + * (<tprevite@gmail.com>)
> + *
> + *
> + * This tool can be run as:
> + * ./intel_dp_compliance  It will wait till you start compliance suite from
> + * DPR 120.
> + * ./intel_dp_compliance -h  This will open the help
> + * ./intel_dp_compliance -i  This will provide information about current
> + * connectors/CRTCs. This can be used for debugging purpose.
> + *
> + * Authors:
> + *    Manasi Navare <manasi.d.navare@intel.com>
> + *
> + * Elements of the modeset code adapted from David Herrmann's
> + * DRM modeset example
> + *
> + */
> +#include "igt.h"
> +#include <errno.h>
> +#include <getopt.h>
> +#include <math.h>
> +#include <stdint.h>
> +#include <stdbool.h>
> +#include <strings.h>
> +#include <unistd.h>
> +#include <termios.h>
> +#include <sys/poll.h>
> +#include <sys/time.h>
> +#include <sys/ioctl.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <sys/select.h>
> +#include <assert.h>
> +#include <signal.h>
> +#include <fcntl.h>
> +#include <time.h>
> +
> +#include "intel_dp_compliance.h"
> +
> +#include <stdlib.h>
> +#include <signal.h>
> +
> +/* User Input definitions */
> +#define HELP_DESCRIPTION 1
> +
> +/* Debugfs file definitions */
> +#define INTEL_DP_TEST_TYPE_FILE                "i915_dp_test_type"
> +#define INTEL_DP_TEST_ACTIVE_FILE      "i915_dp_test_active"
> +#define INTEL_DP_TEST_DATA_FILE                "i915_dp_test_data"
> +
> +/* DRM definitions - must be kept in sync with the DRM header */
> +#define DP_TEST_LINK_TRAINING          (1 << 0)
> +#define DP_TEST_LINK_VIDEO_PATTERN     (1 << 1)
> +#define DP_TEST_LINK_EDID_READ         (1 << 2)
> +#define DP_TEST_LINK_PHY_TEST_PATTERN  (1 << 3) /* DPCD >= 1.1 */
> +
> +#define DP_COMPLIANCE_TEST_TYPE_MASK   (DP_TEST_LINK_TRAINING      |   \
> +                                        DP_TEST_LINK_VIDEO_PATTERN |   \
> +                                        DP_TEST_LINK_EDID_READ     |   \
> +                                        DP_TEST_LINK_PHY_TEST_PATTERN)
> +
> +/* NOTE: These must be kept in sync with the definitions in intel_dp.c */
> +#define INTEL_DP_EDID_SHIFT_MASK       0
> +#define INTEL_DP_EDID_OK               (0 << INTEL_DP_EDID_SHIFT_MASK)
> +#define INTEL_DP_EDID_CORRUPT          (1 << INTEL_DP_EDID_SHIFT_MASK)
> +#define INTEL_DP_RESOLUTION_SHIFT_MASK 0
> +#define INTEL_DP_RESOLUTION_PREFERRED  (1 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> +#define INTEL_DP_RESOLUTION_STANDARD   (2 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> +#define INTEL_DP_RESOLUTION_FAILSAFE   (3 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> +#define DP_COMPLIANCE_VIDEO_MODE_MASK  (INTEL_DP_RESOLUTION_PREFERRED  |\
> +                                        INTEL_DP_RESOLUTION_STANDARD   |\
> +                                        INTEL_DP_RESOLUTION_FAILSAFE)
> +
> +/* Global file pointers for the sysfs files */
> +FILE *test_active_fp, *test_data_fp, *test_type_fp;
> +
> +bool video_pattern_flag;
> +
> +/* Video pattern test globals */
> +uint16_t hdisplay;
> +uint16_t vdisplay;
> +uint8_t bitdepth;
> +
> +static int tio_fd;
> +struct termios saved_tio;
> +
> +drmModeRes *resources;
> +int drm_fd, modes;
> +uint64_t tiling = LOCAL_DRM_FORMAT_MOD_NONE;
> +uint32_t depth = 24, stride, bpp;
> +int specified_mode_num = -1, specified_disp_id = -1;
> +int width, height;
> +uint32_t test_crtc;
> +uint32_t test_connector_id;
> +enum {
> +       INTEL_MODE_INVALID = -1,
> +       INTEL_MODE_NONE = 0,
> +       INTEL_MODE_PREFERRED,
> +       INTEL_MODE_STANDARD,
> +       INTEL_MODE_FAILSAFE,
> +       INTEL_MODE_VIDEO_PATTERN_TEST
> +} intel_display_mode;
> +
> +struct test_video_pattern {
> +       uint16_t hdisplay;
> +       uint16_t vdisplay;
> +       uint8_t bitdepth;
> +       uint32_t fb;
> +       uint32_t size;
> +       struct igt_fb fb_pattern;
> +       drmModeModeInfo mode;
> +       uint32_t *pixmap;
> +};
> +
> +struct connector {
> +       uint32_t id;
> +       int mode_valid;
> +       drmModeModeInfo mode, mode_standard, mode_preferred, mode_failsafe;
> +       drmModeConnector *connector;
> +       int crtc;
> +       /* Standard and preferred frame buffer*/
> +       uint32_t fb, fb_width, fb_height, fb_size;
> +       uint8_t *pixmap;
> +       struct igt_fb fb_video_pattern;
> +       /* Failsafe framebuffer - note this is a 16-bit buffer */
> +       uint32_t failsafe_fb, failsafe_width, failsafe_height;
> +       uint32_t failsafe_size;
> +       uint8_t *failsafe_pixmap;
> +       struct igt_fb fb_failsafe_pattern;
> +       struct test_video_pattern test_pattern;
> +};
> +
> +static void clear_test_active(void)
> +{
> +       rewind(test_active_fp);
> +       fprintf(test_active_fp, "%d", 0);
> +       fflush(test_active_fp);
> +}
> +
> +static void setup_debugfs_files(void)
> +{
> +       test_type_fp = igt_debugfs_fopen(INTEL_DP_TEST_TYPE_FILE, "r");
> +       igt_require(test_type_fp);
> +
> +       test_data_fp = igt_debugfs_fopen(INTEL_DP_TEST_DATA_FILE, "r");
> +       igt_require(test_data_fp);
> +
> +       test_active_fp = igt_debugfs_fopen(INTEL_DP_TEST_ACTIVE_FILE, "w+");
> +       igt_require(test_active_fp);
> +
> +       /* Reset the active flag for safety */
> +       clear_test_active();
> +}
> +
> +static unsigned long get_test_type(void)
> +{
> +       unsigned long test_type;
> +       int ret;
> +
> +       if (!test_type_fp)
> +               fprintf(stderr, "Invalid test_type file\r\n");
> +       rewind(test_type_fp);
> +       ret = fscanf(test_type_fp, "%02lx", &test_type);
> +       if (ret < 1 || test_type <= 0) {
> +               igt_warn("test_type read failed - %02lx\r\n", test_type);
> +               return 0;
> +       }
> +
> +       return test_type;
> +}
> +
> +static unsigned long get_test_edid_data(void)
> +{
> +       unsigned long test_data;
> +       int ret;
> +
> +       if (!test_data_fp)
> +               fprintf(stderr, "Invalid test_data file\r\n");
> +
> +       rewind(test_data_fp);
> +       ret = fscanf(test_data_fp, "%lx", &test_data);
> +       if (ret < 1 || test_data <= 0) {
> +               igt_warn("test_data read failed - %lx\r\n", test_data);
> +               return 0;
> +       }
> +
> +       return test_data;
> +}
> +
> +static void get_test_videopattern_data(void)
> +{
> +       int count = 0;
> +       uint16_t video_pattern_value[3];
> +       char video_pattern_attribute[15];
> +       int ret;
> +
> +       if (!test_data_fp)
> +               fprintf(stderr, "Invalid test_data file\r\n");
> +
> +       rewind(test_data_fp);
> +       while (!feof(test_data_fp) && count < 3) {
> +               ret = fscanf(test_data_fp, "%s %u\n", video_pattern_attribute,
> +                      (unsigned int *)&video_pattern_value[count++]);
> +               if (ret < 2) {
> +                       igt_warn("test_data read failed\n");
> +                       return;
> +               }
> +       }
> +
> +       hdisplay = video_pattern_value[0];
> +       vdisplay = video_pattern_value[1];
> +       bitdepth = video_pattern_value[2];
> +       igt_info("Hdisplay = %d\r\n", hdisplay);
> +       igt_info("Vdisplay = %d\r\n", vdisplay);
> +       igt_info("BitDepth = %u\r\n", bitdepth);
> +
> +}
> +
> +static int process_test_request(int test_type)
> +{
> +       int mode;
> +       unsigned long test_data_edid;
> +       bool valid = false;
> +       switch (test_type) {
> +       case DP_TEST_LINK_VIDEO_PATTERN:
> +               video_pattern_flag = true;
> +               get_test_videopattern_data();
> +               mode = INTEL_MODE_VIDEO_PATTERN_TEST;
> +               valid = true;
> +               break;
> +       case DP_TEST_LINK_EDID_READ:
> +               test_data_edid = get_test_edid_data();
> +               mode = (test_data_edid & DP_COMPLIANCE_VIDEO_MODE_MASK) >>
> +                       INTEL_DP_RESOLUTION_SHIFT_MASK;
> +               valid = true;
> +               break;
> +       default:
> +               /* Unknown test type */
> +               fprintf(stderr, "Invalid test request, ignored.\r\n");
> +               break;
> +       }
> +
> +       if (valid)
> +               return update_display(mode, true);
> +
> +       return -1;
> +}
> +
> +static void dump_connectors_fd(int drmfd)
> +{
> +       int i, j;
> +
> +       drmModeRes *mode_resources = drmModeGetResources(drmfd);
> +
> +       if (!mode_resources) {
> +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> +               return;
> +       }
> +
> +       igt_info("Connectors:\n");
> +       igt_info("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
> +       for (i = 0; i < mode_resources->count_connectors; i++) {
> +               drmModeConnector *connector;
> +
> +               connector = drmModeGetConnectorCurrent(drmfd,
> +                                                      mode_resources->connectors[i]);
> +               if (!connector) {
> +                       igt_warn("Could not get connector %i: %s\n",
> +                                mode_resources->connectors[i], strerror(errno));
> +                       continue;
> +               }
> +
> +               igt_info("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
> +                        connector->connector_id,
> +                        connector->encoder_id,
> +                        kmstest_connector_status_str(connector->connection),
> +                        kmstest_connector_type_str(connector->connector_type),
> +                        connector->mmWidth,
> +                        connector->mmHeight,
> +                        connector->count_modes);
> +
> +               if (!connector->count_modes)
> +                       continue;
> +
> +               igt_info("  Modes:\n");
> +               igt_info("  name refresh (Hz) hdisp hss hse htot vdisp ""vss vse vtot flags type clock\n");
> +               for (j = 0; j < connector->count_modes; j++) {
> +                       igt_info("[%d]", j);
> +                       kmstest_dump_mode(&connector->modes[j]);
> +               }
> +
> +               drmModeFreeConnector(connector);
> +       }
> +       igt_info("\n");
> +
> +       drmModeFreeResources(mode_resources);
> +}
> +
> +static void dump_crtcs_fd(int drmfd)
> +{
> +       int i;
> +       drmModeRes *mode_resources;
> +
> +       mode_resources = drmModeGetResources(drmfd);
> +       if (!mode_resources) {
> +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> +               return;
> +       }
> +
> +       igt_info("CRTCs:\n");
> +       igt_info("id\tfb\tpos\tsize\n");
> +       for (i = 0; i < mode_resources->count_crtcs; i++) {
> +               drmModeCrtc *crtc;
> +
> +               crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]);
> +               if (!crtc) {
> +                       igt_warn("Could not get crtc %i: %s\n", mode_resources->crtcs[i], strerror(errno));
> +                       continue;
> +               }
> +               igt_info("%d\t%d\t(%d,%d)\t(%dx%d)\n",
> +                        crtc->crtc_id,
> +                        crtc->buffer_id,
> +                        crtc->x,
> +                        crtc->y,
> +                        crtc->width,
> +                        crtc->height);
> +
> +               kmstest_dump_mode(&crtc->mode);
> +
> +               drmModeFreeCrtc(crtc);
> +       }
> +       igt_info("\n");
> +
> +       drmModeFreeResources(mode_resources);
> +}
> +
> +static void dump_info(void)
> +{
> +       dump_connectors_fd(drm_fd);
> +       dump_crtcs_fd(drm_fd);
> +}
> +
> +static int setup_framebuffers(struct connector *dp_conn)
> +{
> +
> +       dp_conn->fb = igt_create_fb(drm_fd,
> +                                   dp_conn->fb_width, dp_conn->fb_height,
> +                                   DRM_FORMAT_XRGB8888,
> +                                   LOCAL_DRM_FORMAT_MOD_NONE,
> +                                   &dp_conn->fb_video_pattern);
> +       igt_assert(dp_conn->fb);
> +
> +       /* Map the mapping of GEM object into the virtual address space */
> +       dp_conn->pixmap = gem_mmap__gtt(drm_fd,
> +                                       dp_conn->fb_video_pattern.gem_handle,
> +                                       dp_conn->fb_video_pattern.size,
> +                                       PROT_READ | PROT_WRITE);
> +       if (dp_conn->pixmap == NULL)
> +               return -1;
> +
> +       gem_set_domain(drm_fd, dp_conn->fb_video_pattern.gem_handle,
> +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> +       dp_conn->fb_size = dp_conn->fb_video_pattern.size;
> +
> +       /* After filling the device memory with 0s it needs to be unmapped */
> +       memset(dp_conn->pixmap, 0, dp_conn->fb_size);
> +       munmap(dp_conn->pixmap, dp_conn->fb_size);
> +
> +       return 0;
> +}
> +
> +static int setup_failsafe_framebuffer(struct connector *dp_conn)
> +{
> +
> +       dp_conn->failsafe_fb = igt_create_fb(drm_fd,
> +                                            dp_conn->failsafe_width,
> +                                            dp_conn->failsafe_height,
> +                                            DRM_FORMAT_XRGB8888,
> +                                            LOCAL_DRM_FORMAT_MOD_NONE,
> +                                            &dp_conn->fb_failsafe_pattern);
> +       igt_assert(dp_conn->failsafe_fb);
> +
> +       /* Map the mapping of GEM object into the virtual address space */
> +       dp_conn->failsafe_pixmap = gem_mmap__gtt(drm_fd,
> +                                                dp_conn->fb_failsafe_pattern.gem_handle,
> +                                                dp_conn->fb_failsafe_pattern.size,
> +                                                PROT_READ | PROT_WRITE);
> +       if (dp_conn->failsafe_pixmap == NULL)
> +               return -1;
> +
> +       gem_set_domain(drm_fd, dp_conn->fb_failsafe_pattern.gem_handle,
> +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> +       dp_conn->failsafe_size = dp_conn->fb_failsafe_pattern.size;
> +
> +       /* After filling the device framebuffer the mapped memory needs to be freed */
> +       memset(dp_conn->failsafe_pixmap, 0, dp_conn->failsafe_size);
> +       munmap(dp_conn->failsafe_pixmap, dp_conn->failsafe_size);
> +
> +       return 0;
> +
> +}
> +
> +static int setup_video_pattern_framebuffer(struct connector *dp_conn)
> +{
> +       uint32_t  video_width, video_height;
> +
> +       video_width = dp_conn->test_pattern.hdisplay;
> +       video_height = dp_conn->test_pattern.vdisplay;
> +       dp_conn->test_pattern.fb = igt_create_fb(drm_fd,
> +                                                video_width, video_height,
> +                                                DRM_FORMAT_XRGB8888,
> +                                                LOCAL_DRM_FORMAT_MOD_NONE,
> +                                                &dp_conn->test_pattern.fb_pattern);
> +       igt_assert(dp_conn->test_pattern.fb);
> +
> +       /* Map the mapping of GEM object into the virtual address space */
> +       dp_conn->test_pattern.pixmap = gem_mmap__gtt(drm_fd,
> +                                                    dp_conn->test_pattern.fb_pattern.gem_handle,
> +                                                    dp_conn->test_pattern.fb_pattern.size,
> +                                                    PROT_READ | PROT_WRITE);
> +       if (dp_conn->test_pattern.pixmap == NULL)
> +               return -1;
> +
> +       gem_set_domain(drm_fd, dp_conn->test_pattern.fb_pattern.gem_handle,
> +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> +
> +       dp_conn->test_pattern.size = dp_conn->test_pattern.fb_pattern.size;
> +
> +       memset(dp_conn->test_pattern.pixmap, 0, dp_conn->test_pattern.size);
> +       return 0;
> +
> +}
> +
> +static int fill_framebuffer(struct connector *dp_conn)
> +{
> +       uint32_t tile_height, tile_width, video_width, video_height;
> +       uint32_t *red_ptr, *green_ptr, *blue_ptr, *white_ptr, *src_ptr, *dst_ptr;
> +       int x, y;
> +       int32_t pixel_val;
> +
> +       video_width = dp_conn->test_pattern.hdisplay;
> +       video_height = dp_conn->test_pattern.vdisplay;
> +
> +       tile_height = 64;
> +       tile_width = 1 <<  (dp_conn->test_pattern.bitdepth);
> +
> +       red_ptr = dp_conn->test_pattern.pixmap;
> +       green_ptr = red_ptr + (video_width * tile_height);
> +       blue_ptr = green_ptr + (video_width * tile_height);
> +       white_ptr = blue_ptr + (video_width * tile_height);
> +       x = 0;
> +
> +       /* Fill the frame buffer with video pattern from CTS 3.1.5 */
> +       while (x < video_width) {
> +               for (pixel_val = 0; pixel_val < 256;
> +                    pixel_val = pixel_val + (256 / tile_width)) {
> +                       red_ptr[x] = pixel_val << 16;
> +                       green_ptr[x] = pixel_val << 8;
> +                       blue_ptr[x] = pixel_val << 0;
> +                       white_ptr[x] = red_ptr[x] | green_ptr[x] | blue_ptr[x];
> +                       if (++x >= video_width)
> +                               break;
> +               }
> +       }
> +       for (y = 0; y < video_height; y++) {
> +               if (y == 0 || y == 64 || y == 128 || y == 192)
> +                       continue;
> +               switch ((y / tile_height) % 4) {
> +               case 0:
> +                       src_ptr = red_ptr;
> +                       break;
> +               case 1:
> +                       src_ptr = green_ptr;
> +                       break;
> +               case 2:
> +                       src_ptr = blue_ptr;
> +                       break;
> +               case 3:
> +                       src_ptr = white_ptr;
> +                       break;
> +               }
> +               dst_ptr = dp_conn->test_pattern.pixmap + (y * video_width);
> +               memcpy(dst_ptr, src_ptr, (video_width * 4));
> +       }
> +       munmap(dp_conn->test_pattern.pixmap,
> +              dp_conn->test_pattern.size);
> +       return 0;
> +}
> +
> +static int set_test_mode(struct connector *dp_conn)
> +{
> +       int ret = 0;
> +       int i;
> +       bool found_std = false, found_fs = false;
> +       drmModeConnector *c = dp_conn->connector;
> +
> +       /* Ignore any disconnected devices */
> +       if (c->connection != DRM_MODE_CONNECTED) {
> +               igt_warn("Connector %u disconnected\r\n", c->connector_id);
> +               return -ENOENT;
> +       }
> +       igt_info("Connector setup:\r\n");
> +       /* Setup preferred mode - should be mode[0] in the list */
> +       dp_conn->mode_preferred = c->modes[0];
> +       dp_conn->fb_width = c->modes[0].hdisplay;
> +       dp_conn->fb_height = c->modes[0].vdisplay;
> +
> +       dp_conn->test_pattern.mode = c->modes[0];
> +       dp_conn->test_pattern.mode.hdisplay = c->modes[0].hdisplay;
> +       dp_conn->test_pattern.mode.vdisplay = c->modes[0].vdisplay;
> +
> +       igt_info("Preferred mode (mode 0) for connector %u is %ux%u\r\n",
> +                dp_conn->id, c->modes[0].hdisplay, c->modes[0].vdisplay);
> +       fflush(stdin);
> +
> +       for (i = 1; i < c->count_modes; i++) {
> +               /* Standard mode is 800x600@60 */
> +               if (c->modes[i].hdisplay == 800 &&
> +                   c->modes[i].vdisplay == 600 &&
> +                   c->modes[i].vrefresh == 60 &&
> +                   found_std == false) {
> +                       dp_conn->mode_standard = c->modes[i];
> +                       igt_info("Standard mode (%d) for connector %u is %ux%u\r\n",
> +                                i,
> +                                c->connector_id,
> +                                c->modes[i].hdisplay,
> +                                c->modes[i].vdisplay);
> +                       found_std = true;
> +               }
> +               /* Failsafe mode is 640x480@60 */
> +               if (c->modes[i].hdisplay == 640 &&
> +                   c->modes[i].vdisplay == 480 &&
> +                   c->modes[i].vrefresh == 60 &&
> +                   found_fs == false) {
> +                       dp_conn->mode_failsafe = c->modes[i];
> +                       dp_conn->failsafe_width = c->modes[i].hdisplay;
> +                       dp_conn->failsafe_height = c->modes[i].vdisplay;
> +                       igt_info("Failsafe mode (%d) for connector %u is %ux%u\r\n",
> +                                i,
> +                                c->connector_id,
> +                                c->modes[i].hdisplay,
> +                                c->modes[i].vdisplay);
> +                       found_fs = true;
> +               }
> +       }
> +
> +       ret = setup_framebuffers(dp_conn);
> +       if (ret) {
> +               igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
> +                        c->connector_id, ret);
> +               return ret;
> +       }
> +
> +       if (found_fs) {
> +               ret = setup_failsafe_framebuffer(dp_conn);
> +               if (ret) {
> +                       igt_warn("Creating failsafe framebuffer for connector %u failed (%d)\r\n",
> +                                c->connector_id, ret);
> +                       return ret;
> +               }
> +       }
> +
> +       if (video_pattern_flag) {
> +               dp_conn->test_pattern.hdisplay = hdisplay;
> +               dp_conn->test_pattern.vdisplay = vdisplay;
> +               dp_conn->test_pattern.bitdepth = bitdepth;
> +
> +               ret = setup_video_pattern_framebuffer(dp_conn);
> +               if (ret) {
> +                       igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
> +                                c->connector_id, ret);
> +                       return ret;
> +               }
> +
> +               ret = fill_framebuffer(dp_conn);
> +               if (ret) {
> +                       igt_warn("Filling framebuffer for connector %u failed (%d)\r\n",
> +                                c->connector_id, ret);
> +                       return ret;
> +               }
> +       }
> +
> +       return ret;
> +}
> +
> +static int set_video(int mode, struct connector *test_connector)
> +{
> +       drmModeModeInfo *requested_mode;
> +       uint32_t required_fb_id;
> +       struct igt_fb required_fb;
> +       int ret = 0;
> +
> +       switch (mode) {
> +       case INTEL_MODE_NONE:
> +               igt_info("NONE\r\n");
> +               ret = drmModeSetCrtc(drm_fd, test_connector->crtc,
> +                                    -1, 0, 0, NULL, 0, NULL);
> +               goto out;
> +       case INTEL_MODE_PREFERRED:
> +               igt_info("PREFERRED\r\n");
> +               requested_mode =  &test_connector->mode_preferred;
> +               required_fb_id = test_connector->fb;
> +               required_fb = test_connector->fb_video_pattern;
> +               break;
> +       case INTEL_MODE_STANDARD:
> +               igt_info("STANDARD\r\n");
> +               requested_mode =  &test_connector->mode_standard;
> +               required_fb_id = test_connector->fb;
> +               required_fb = test_connector->fb_video_pattern;
> +               break;
> +       case INTEL_MODE_FAILSAFE:
> +               igt_info("FAILSAFE\r\n");
> +               requested_mode =  &test_connector->mode_failsafe;
> +               required_fb_id = test_connector->failsafe_fb;
> +               required_fb = test_connector->fb_failsafe_pattern;
> +               break;
> +       case INTEL_MODE_VIDEO_PATTERN_TEST:
> +               igt_info("VIDEO PATTERN TEST\r\n");
> +               requested_mode = &test_connector->test_pattern.mode;
> +               required_fb_id = test_connector->test_pattern.fb;
> +               required_fb = test_connector->test_pattern.fb_pattern;
> +               break;
> +       case INTEL_MODE_INVALID:
> +       default:
> +               igt_warn("INVALID! (%08x) Mode set aborted!\r\n", mode);
> +               return -1;
> +       }
> +
> +       igt_info("CRTC(%u):", test_connector->crtc);
> +       kmstest_dump_mode(requested_mode);
> +       ret = drmModeSetCrtc(drm_fd, test_connector->crtc, required_fb_id, 0, 0,
> +                            &test_connector->id, 1, requested_mode);
> +       if (ret) {
> +               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
> +                        requested_mode->hdisplay, requested_mode->vdisplay,
> +                        requested_mode->vrefresh, strerror(errno));
> +               igt_remove_fb(drm_fd, &required_fb);
> +
> +       }
> +       /* Keep the pattern on output lines for 1 sec for DPR-120 to detect it */
> +       sleep(1);
> +
> +out:
> +       if (ret) {
> +               igt_warn("Failed to set CRTC for connector %u\r\n",
> +                        test_connector->id);
> +       }
> +
> +       return ret;
> +}
> +
> +static int
> +set_default_mode(struct connector *c, bool set_mode)
> +{
> +       unsigned int fb_id = 0;
> +       struct igt_fb fb_info;
> +       int ret = 0;
> +
> +       if (!set_mode) {
> +               ret = drmModeSetCrtc(drm_fd, c->crtc, 0, 0, 0,
> +                                    NULL, 0, NULL);
> +               if (ret)
> +                       igt_warn("Failed to unset mode");
> +               return ret;
> +       }
> +
> +       c->mode = c->connector->modes[0];
> +
> +       width = c->mode.hdisplay;
> +       height = c->mode.vdisplay;
> +
> +       fb_id = igt_create_pattern_fb(drm_fd, width, height,
> +                                     DRM_FORMAT_XRGB8888,
> +                                     tiling, &fb_info);
> +
> +       igt_info("CRTC(%u):[%d]", c->crtc, 0);
> +       kmstest_dump_mode(&c->mode);
> +       drmModeSetCrtc(drm_fd, c->crtc, -1, 0, 0, NULL, 0, NULL);
> +       ret = drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
> +                            &c->id, 1, &c->mode);
> +       if (ret) {
> +               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
> +                        width, height, c->mode.vrefresh, strerror(errno));
> +               igt_remove_fb(drm_fd, &fb_info);
> +
> +       }
> +
> +       return ret;
> +}
> +
> +static uint32_t find_crtc_for_connector(drmModeConnector *c)
> +{
> +       drmModeEncoder *e;
> +       uint32_t possible_crtcs;
> +       int i, j;
> +
> +       for (i = 0; i < c->count_encoders; i++) {
> +               e = drmModeGetEncoder(drm_fd, c->encoders[i]);
> +               possible_crtcs = e->possible_crtcs;
> +               drmModeFreeEncoder(e);
> +
> +               for (j = 0; possible_crtcs >> j; j++)
> +                       if (possible_crtcs & (1 << j))
> +                               return resources->crtcs[j];
> +       }
> +       return 0;
> +}
> +
> +/*
> + * Re-probe connectors and do a modeset based on test request or
> + * in case of a hotplug uevent.
> + *
> + * @mode: Video mode requested by the test
> + * @is_compliance_test: 1: If it is a compliance test
> + *                      0: If it is a hotplug event
> + *
> + * Returns:
> + * 0: On Success
> + * -1: On failure
> + */
> +int update_display(int mode, bool is_compliance_test)
> +{
> +       struct connector *connectors, *conn;
> +       int cnt, ret = 0;
> +       bool set_mode;
> +
> +       resources = drmModeGetResources(drm_fd);
> +       if (!resources) {
> +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> +               return -1;
> +       }
> +
> +       connectors = calloc(resources->count_connectors,
> +                           sizeof(struct connector));
> +       if (!connectors)
> +               return -1;
> +
> +       /* Find any connected displays */
> +       for (cnt = 0; cnt < resources->count_connectors; cnt++) {
> +               drmModeConnector *c;
> +
> +               conn = &connectors[cnt];
> +               conn->id = resources->connectors[cnt];
> +               c = drmModeGetConnector(drm_fd, conn->id);
> +               if (c->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
> +                   c->connection == DRM_MODE_CONNECTED) {
> +                       test_connector_id = c->connector_id;
> +                       conn->connector = c;
> +                       conn->crtc = find_crtc_for_connector(c);
> +                       test_crtc = conn->crtc;
> +                       set_mode = true;
> +                       break;
> +               } else if (c->connector_id == test_connector_id &&
> +                          c->connection == DRM_MODE_DISCONNECTED) {
> +                       conn->connector = c;
> +                       conn->crtc = test_crtc;
> +                       set_mode = false;
> +                       break;
> +               }
> +       }
> +
> +       if (cnt == resources->count_connectors) {
> +               ret = -1;
> +               goto err;
> +       }
> +
> +       if (is_compliance_test) {
> +               set_test_mode(conn);
> +               ret = set_video(INTEL_MODE_NONE, conn);
> +               ret = set_video(mode, conn);
> +
> +       } else
> +               ret = set_default_mode(conn, set_mode);
> +
> + err:
> +       drmModeFreeConnector(conn->connector);
> +       /* Error condition if no connected displays */
> +       free(connectors);
> +       drmModeFreeResources(resources);
> +       return ret;
> +}
> +
> +static const char optstr[] = "hi";
> +
> +static void __attribute__((noreturn)) usage(char *name, char opt)
> +{
> +       igt_info("usage: %s [-hi]\n", name);
> +       igt_info("\t-i\tdump info\n");
> +       igt_info("\tDefault is to respond to DPR-120 tests\n");
> +       exit((opt != 'h') ? -1 : 0);
> +}
> +
> +static void cleanup_debugfs(void)
> +{
> +       fclose(test_active_fp);
> +       fclose(test_data_fp);
> +       fclose(test_type_fp);
> +}
> +
> +static void __attribute__((noreturn)) cleanup_and_exit(int ret)
> +{
> +       cleanup_debugfs();
> +       close(drm_fd);
> +       igt_info("Compliance testing application exiting\n");
> +       exit(ret);
> +}
> +
> +static void cleanup_test(void)
> +{
> +       video_pattern_flag = false;
> +       hdisplay = 0;
> +       vdisplay = 0;
> +       bitdepth = 0;
> +}
> +
> +static void read_test_request(void)
> +{
> +       unsigned long test_type;
> +
> +       test_type = get_test_type();
> +       process_test_request(test_type);
> +       cleanup_test();
> +       clear_test_active();
> +}
> +
> +static gboolean test_handler(GIOChannel *source, GIOCondition condition,
> +                            gpointer data)
> +{
> +       unsigned long test_active;
> +       int ret;
> +
> +       rewind(test_active_fp);
> +
> +       ret = fscanf(test_active_fp, "%lx", &test_active);
> +       if (ret < 1)
> +               return FALSE;
> +
> +       if (test_active)
> +               read_test_request();
> +       return TRUE;
> +}
> +
> +static gboolean input_event(GIOChannel *source, GIOCondition condition,
> +                               gpointer data)
> +{
> +       gchar buf[2];
> +       gsize count;
> +
> +       count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf));
> +       if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) {
> +               cleanup_and_exit(0);
> +       }
> +
> +       return TRUE;
> +}
> +
> +static void enter_exec_path(char **argv)
> +{
> +       char *exec_path = NULL;
> +       char *pos = NULL;
> +       short len_path = 0;
> +       int ret;
> +
> +       len_path = strlen(argv[0]);
> +       exec_path = (char *) malloc(len_path);
> +
> +       memcpy(exec_path, argv[0], len_path);
> +       pos = strrchr(exec_path, '/');
> +       if (pos != NULL)
> +               *(pos+1) = '\0';
> +
> +       ret = chdir(exec_path);
> +       igt_assert_eq(ret, 0);
> +       free(exec_path);
> +}
> +
> +static void restore_termio_mode(int sig)
> +{
> +       tcsetattr(tio_fd, TCSANOW, &saved_tio);
> +       close(tio_fd);
> +}
> +
> +static void set_termio_mode(void)
> +{
> +       struct termios tio;
> +
> +       /* don't attempt to set terminal attributes if not in the foreground
> +        * process group
> +        */
> +       if (getpgrp() != tcgetpgrp(STDOUT_FILENO))
> +               return;
> +
> +       tio_fd = dup(STDIN_FILENO);
> +       tcgetattr(tio_fd, &saved_tio);
> +       igt_install_exit_handler(restore_termio_mode);
> +       tio = saved_tio;
> +       tio.c_lflag &= ~(ICANON | ECHO);
> +       tcsetattr(tio_fd, TCSANOW, &tio);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +       int c;
> +       int ret = 0;
> +       GIOChannel *stdinchannel, *testactive_channel;
> +       GMainLoop *mainloop;
> +       bool opt_dump_info = false;
> +       struct option long_opts[] = {
> +               {"help-description", 0, 0, HELP_DESCRIPTION},
> +               {"help", 0, 0, 'h'},
> +       };
> +
> +       igt_skip_on_simulation();
> +
> +       enter_exec_path(argv);
> +
> +       while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) {
> +               switch (c) {
> +               case 'i':
> +                       opt_dump_info = true;
> +                       break;
> +               case HELP_DESCRIPTION:
> +                       igt_info("DP Compliance Test Suite using DPR-120\n");
> +                       igt_info("EDID tests\n");
> +                       igt_info("Video Pattern Generation tests\n");
> +                       exit(0);
> +                       break;
> +               default:
> +                       /* fall through */
> +               case 'h':
> +                       usage(argv[0], c);
> +                       break;
> +               }
> +       }
> +
> +       set_termio_mode();
> +
> +       igt_info("*************DP Compliance Testing using DPR-120*************\n");
> +       igt_info("Waiting for test request......\n");
> +       drm_fd = drm_open_driver(DRIVER_ANY);
> +
> +       kmstest_set_vt_graphics_mode();
> +       setup_debugfs_files();
> +       cleanup_test();
> +
> +       if (opt_dump_info) {
> +               dump_info();
> +               goto out_close;
> +       }
> +
> +       /* Get the DP connector ID and CRTC */
> +       if (update_display(0, false)) {
> +               igt_warn("Failed to set default mode\n");
> +               ret = -1;
> +               goto out_close;
> +       }
> +
> +       mainloop = g_main_loop_new(NULL, FALSE);
> +       if (!mainloop) {
> +               igt_warn("Failed to create GMainLoop\n");
> +               ret = -1;
> +               goto out_close;
> +       }
> +
> +       if (!intel_dp_compliance_setup_hotplug()) {
> +               igt_warn("Failed to initialize hotplug support\n");
> +               goto out_mainloop;
> +       }
> +
> +       testactive_channel = g_io_channel_unix_new(fileno(test_active_fp));
> +       if (!testactive_channel) {
> +               igt_warn("Failed to create test_active GIOChannel\n");
> +               goto out_close;
> +       }
> +
> +       ret = g_io_add_watch(testactive_channel, G_IO_IN | G_IO_ERR,
> +                            test_handler, NULL);
> +       if (ret < 0) {
> +               igt_warn("Failed to add watch on udev GIOChannel\n");
> +               goto out_close;
> +       }
> +
> +       stdinchannel = g_io_channel_unix_new(0);
> +       if (!stdinchannel) {
> +               igt_warn("Failed to create stdin GIOChannel\n");
> +               goto out_hotplug;
> +       }
> +
> +       ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event,
> +                            NULL);
> +       if (ret < 0) {
> +               igt_warn("Failed to add watch on stdin GIOChannel\n");
> +               goto out_stdio;
> +       }
> +
> +       ret = 0;
> +
> +       g_main_loop_run(mainloop);
> +
> +out_stdio:
> +       g_io_channel_shutdown(stdinchannel, TRUE, NULL);
> +out_hotplug:
> +       intel_dp_compliance_cleanup_hotplug();
> +out_mainloop:
> +       g_main_loop_unref(mainloop);
> +out_close:
> +       cleanup_debugfs();
> +       close(drm_fd);
> +
> +       igt_assert_eq(ret, 0);
> +
> +       igt_info("Compliance testing application exiting\n");
> +       igt_exit();
> +}
> diff --git a/tools/intel_dp_compliance.h b/tools/intel_dp_compliance.h
> new file mode 100644
> index 0000000..ade1e2f
> --- /dev/null
> +++ b/tools/intel_dp_compliance.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright 2010 Intel Corporation
> + * Manasi Navare <manasi.d.navare@intel.com>
> + *
> + * 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 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 <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <glib.h>
> +
> +extern int drm_fd;
> +
> +gboolean intel_dp_compliance_setup_hotplug(void);
> +void intel_dp_compliance_cleanup_hotplug(void);
> +
> +/* called by the hotplug code */
> +int update_display(int mode, bool is_compliance_test);
> diff --git a/tools/intel_dp_compliance_hotplug.c b/tools/intel_dp_compliance_hotplug.c
> new file mode 100644
> index 0000000..7c7ea65
> --- /dev/null
> +++ b/tools/intel_dp_compliance_hotplug.c
> @@ -0,0 +1,123 @@
> +/*
> + * Copyright 2010 Intel Corporation
> + *   Jesse Barnes <jesse.barnes@intel.com>
> + *
> + * 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 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.h"
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#include <sys/stat.h>
> +
> +#include "intel_dp_compliance.h"
> +#include <libudev.h>
> +static struct udev_monitor *uevent_monitor;
> +static struct udev *udev;
> +static GIOChannel *udevchannel;
> +
> +static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
> +                             gpointer data)
> +{
> +       struct udev_device *dev;
> +       dev_t udev_devnum;
> +       struct stat s;
> +       const char *hotplug;
> +
> +       dev = udev_monitor_receive_device(uevent_monitor);
> +       if (!dev)
> +               goto out;
> +
> +       udev_devnum = udev_device_get_devnum(dev);
> +       fstat(drm_fd, &s);
> +
> +       hotplug = udev_device_get_property_value(dev, "HOTPLUG");
> +
> +       if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
> +           hotplug && atoi(hotplug) == 1)
> +               update_display(0, false);
> +
> +       udev_device_unref(dev);
> +out:
> +       return TRUE;
> +}
> +
> +
> +gboolean intel_dp_compliance_setup_hotplug(void)
> +{
> +       int ret;
> +
> +       udev = udev_new();
> +       if (!udev) {
> +               igt_warn("Failed to create udev object\n");
> +               goto out;
> +       }
> +
> +       uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
> +       if (!uevent_monitor) {
> +               igt_warn("Failed to create udev event monitor\n");
> +               goto out;
> +       }
> +
> +       ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
> +                                                             "drm",
> +                                                             "drm_minor");
> +       if (ret < 0) {
> +               igt_warn("Failed to filter for drm events\n");
> +               goto out;
> +       }
> +
> +       ret = udev_monitor_enable_receiving(uevent_monitor);
> +       if (ret < 0) {
> +               igt_warn("Failed to enable udev event reception\n");
> +               goto out;
> +       }
> +
> +       udevchannel =
> +               g_io_channel_unix_new(udev_monitor_get_fd(uevent_monitor));
> +       if (!udevchannel) {
> +               igt_warn("Failed to create udev GIOChannel\n");
> +               goto out;
> +       }
> +
> +       ret = g_io_add_watch(udevchannel, G_IO_IN | G_IO_ERR, hotplug_event,
> +                            udev);
> +       if (ret < 0) {
> +               igt_warn("Failed to add watch on udev GIOChannel\n");
> +               goto out;
> +       }
> +
> +       return TRUE;
> +
> +out:
> +       intel_dp_compliance_cleanup_hotplug();
> +       return FALSE;
> +}
> +
> +void intel_dp_compliance_cleanup_hotplug(void)
> +{
> +       if (udevchannel)
> +               g_io_channel_shutdown(udevchannel, TRUE, NULL);
> +       if (uevent_monitor)
> +               udev_monitor_unref(uevent_monitor);
> +       if (udev)
> +               udev_unref(udev);
> +}
> --
> 2.7.4
>
Navare, Manasi Jan. 18, 2017, 6:28 p.m. UTC | #2
On Wed, Jan 11, 2017 at 03:44:12PM +0200, Petri Latvala wrote:
> 
> Hi
> 
> The copyright statements still need the year
> corrected. intel_dp_compliance needs to be added to tools/.gitignore
> 
> Some new comments also:
> 
> - Why do some of the prints have \r\n?

The \r\n is required in some of the prints so that the output prints are properly aligned.


> - Building intel_dp_compliance should actually be made conditional upon HAVE_UDEV
>
I didnt find any conditional HAVE_UDEV builds in the existing Makefile.
How can I build intel-dp_compliance conditionally on HAVE_UDEV?
Could you point me to some example in the existing Makefile?

Manasi 
> 
> 
> --
> Petri Latvala
> 
> 
> 
> On Fri, Dec 23, 2016 at 09:47:48AM +0200, Pandiyan, Dhinakaran wrote:
> > I have addressed review comments that Petri, Jim had for this patch along with making some small changes for error handling. The functionality is mostly unchanged from Manasi's version.
> > 
> > -DK
> > ________________________________________
> > From: Pandiyan, Dhinakaran
> > Sent: Thursday, December 22, 2016 11:41 PM
> > To: intel-gfx@lists.freedesktop.org
> > Cc: jim.bride@linux.intel.com; Navare, Manasi D; Latvala, Petri; Vlad, Marius C; Daniel Vetter; Pandiyan, Dhinakaran
> > Subject: [PATCH i-g-t v3] tools: Add intel_dp_compliance for DisplayPort 1.2 compliance automation
> > 
> > From: "Navare, Manasi D" <manasi.d.navare@intel.com>
> > 
> > This is the userspace component of the Displayport Compliance
> > testing software required for compliance testing of the I915
> > Display Port driver. This must be running in order to successfully
> > complete Display Port compliance testing. This app and the kernel
> > code that accompanies it has been written to satify the requirements
> > of the Displayport Link CTS 1.2 rev1.1 specification from VESA.
> > Note that this application does not support eDP compliance testing.
> > This utility has an automation support for the Link training tests
> > (4.3.1.1. - 4.3.2.3), EDID tests (4.2.2.3
> > - 4.2.2.6) and Video Pattern generation tests (4.3.3.1) from CTS
> > specification 1.2 Rev 1.1.
> > 
> > This tool has the support for responding to the hotplug uevents
> > sent by compliance testting unit after each test.
> > 
> > The Linux DUT running this utility must be in text (console) mode
> > and cannot have any other display manager running. Since this uses
> > sysfs nodes for kernel interaction, this utility should be run as
> > Root. Once this user application is up and running, waiting for
> > test requests, the test appliance software on the windows host
> > can now be used to execute the compliance tests.
> > 
> > This app is based on some prior work done in April 2015 (by
> > Todd Previte <tprevite@gmail.com>)
> > 
> > v2:
> > * Add mode unset on hotplug uevent on disconnect (Manasi Navare)
> > 
> > v3:
> > Made capitalization consistent
> > Reduced line lengths
> > Added return value checks
> > Changed how GLib is linked
> > Fixed build warnings
> > 
> > Cc: Petri Latvala <petri.latvala@intel.com>
> > Cc: Marius Vlad <marius.c.vlad@intel.com>
> > Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> > Signed-off-by: Manasi Navare <manasi.d.navare@intel.com>
> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
> > ---
> >  tools/Makefile.am                   |    1 +
> >  tools/Makefile.sources              |    7 +
> >  tools/intel_dp_compliance.c         | 1104 +++++++++++++++++++++++++++++++++++
> >  tools/intel_dp_compliance.h         |   35 ++
> >  tools/intel_dp_compliance_hotplug.c |  123 ++++
> >  5 files changed, 1270 insertions(+)
> >  create mode 100644 tools/intel_dp_compliance.c
> >  create mode 100644 tools/intel_dp_compliance.h
> >  create mode 100644 tools/intel_dp_compliance_hotplug.c
> > 
> > diff --git a/tools/Makefile.am b/tools/Makefile.am
> > index 18f86f6..bd8f512 100644
> > --- a/tools/Makefile.am
> > +++ b/tools/Makefile.am
> > @@ -16,6 +16,7 @@ AM_CFLAGS = $(DEBUG_CFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \
> >  LDADD = $(top_builddir)/lib/libintel_tools.la
> >  AM_LDFLAGS = -Wl,--as-needed
> > 
> > +intel_dp_compliance_LDADD = $(top_builddir)/lib/libintel_tools.la $(GLIB_LIBS)
> > 
> >  # aubdumper
> > 
> > diff --git a/tools/Makefile.sources b/tools/Makefile.sources
> > index e2451ea..e8ce891 100644
> > --- a/tools/Makefile.sources
> > +++ b/tools/Makefile.sources
> > @@ -13,6 +13,7 @@ tools_prog_lists =            \
> >         intel_bios_reader       \
> >         intel_display_crc       \
> >         intel_display_poller    \
> > +       intel_dp_compliance     \
> >         intel_forcewaked        \
> >         intel_gpu_frequency     \
> >         intel_firmware_decode   \
> > @@ -56,3 +57,9 @@ intel_l3_parity_SOURCES =     \
> >         intel_l3_parity.h       \
> >         intel_l3_udev_listener.c
> > 
> > +intel_dp_compliance_SOURCES = \
> > +        intel_dp_compliance.c \
> > +        intel_dp_compliance.h \
> > +        intel_dp_compliance_hotplug.c \
> > +        $(NULL)
> > +
> > diff --git a/tools/intel_dp_compliance.c b/tools/intel_dp_compliance.c
> > new file mode 100644
> > index 0000000..df1ca10
> > --- /dev/null
> > +++ b/tools/intel_dp_compliance.c
> > @@ -0,0 +1,1104 @@
> > +/*
> > + * 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.
> > + *
> > + * Displayport Compliance Testing Application
> > + *
> > + * This is the userspace component of the Displayport Compliance testing
> > + * software required for compliance testing of the I915 Display Port driver.
> > + * This must be running in order to successfully complete Display Port
> > + * compliance testing. This app and the kernel code that accompanies it has been
> > + * written to satify the requirements of the Displayport Link CTS 1.2 rev1.1
> > + * specification from VESA. Note that this application does not support eDP
> > + * compliance testing.
> > + *
> > + * Compliance Testing requires several components:
> > + *   - A kernel build that contains the patch set for DP compliance support
> > + *   - A Displayport Compliance Testing appliance such as Unigraf-DPR120
> > + *   - This user application
> > + *   - A windows host machine to run the DPR test software
> > + *   - Root access on the DUT due to the use of sysfs utility
> > + *
> > + * Test Setup:
> > + * It is strongly recommended that the windows host, test appliance and DUT
> > + * be freshly restarted before any testing begins to ensure that any previous
> > + * configurations and settings will not interfere with test process. Refer to
> > + * the test appliance documentation for setup, software installation and
> > + * operation specific to that device.
> > + *
> > + * The Linux DUT must be in text (console) mode and cannot have any other
> > + * display manager running. You must be logged in as root to run this user app.
> > + * Once the user application is up and running, waiting for test requests, the
> > + * software on the windows host can now be used to execute the compliance tests.
> > + *
> > + * This userspace application supports following tests from the DP CTS Spec
> > + * Rev 1.1:
> > + *   - Link Training Tests: Supports tests 4.3.1.1 to 4.3.2.3
> > + *   - EDID Tests: Supports EDID read (4.2.2.3),EDID Read failure and corruption
> > + *     detection tests (4.2.2.4, 4.2.2.5, 4.2.2.6)
> > + *   - Video Pattern generation tests: This supports only the 24 and 18bpp color
> > + *     ramp test pattern (4.3.3.1).
> > + *
> > + * Connections (required):
> > + *   - Test Appliance connected to the external Displayport connector on the DUT
> > + *   - Test Appliance Monitor Out connected to Displayport connector on the
> > + * monitor
> > + *   - Test appliance connected to the Windows Host via USB
> > + *
> > + * Debugfs Files:
> > + * The file root for all  the debugfs file:
> > + * /sys/kernel/debug/dri/0/
> > + *
> > + * The specific files are as follows:
> > + *
> > + * i915_dp_test_active
> > + * A simple flag that indicates whether or not compliance testing is currently
> > + * active in the kernel. This flag is polled by userspace and once set, invokes
> > + * the test handler in the user app. This flag is set by the test handler in the
> > + * kernel after reading the registers requested by the test appliance.
> > + *
> > + * i915_dp_test_data
> > + * Test data is used by the kernel to pass parameters to the user app. Eg: In
> > + * case of EDID tests, the data that is delivered to the userspace is the video
> > + * mode to be set for the test.
> > + * In case of video pattern test, the data that is delivered to the userspace is
> > + * the width and height of the test pattern and the bits per color value.
> > + *
> > + * i915_dp_test_type
> > + * The test type variable instructs the user app as to what the requested test
> > + * was from the sink device. These values defined at the top of the application's
> > + * main implementation file must be kept in sync with the values defined in the
> > + * kernel's drm_dp_helper.h file.
> > + * This app is based on some prior work submitted in April 2015 by Todd Previte
> > + * (<tprevite@gmail.com>)
> > + *
> > + *
> > + * This tool can be run as:
> > + * ./intel_dp_compliance  It will wait till you start compliance suite from
> > + * DPR 120.
> > + * ./intel_dp_compliance -h  This will open the help
> > + * ./intel_dp_compliance -i  This will provide information about current
> > + * connectors/CRTCs. This can be used for debugging purpose.
> > + *
> > + * Authors:
> > + *    Manasi Navare <manasi.d.navare@intel.com>
> > + *
> > + * Elements of the modeset code adapted from David Herrmann's
> > + * DRM modeset example
> > + *
> > + */
> > +#include "igt.h"
> > +#include <errno.h>
> > +#include <getopt.h>
> > +#include <math.h>
> > +#include <stdint.h>
> > +#include <stdbool.h>
> > +#include <strings.h>
> > +#include <unistd.h>
> > +#include <termios.h>
> > +#include <sys/poll.h>
> > +#include <sys/time.h>
> > +#include <sys/ioctl.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <sys/select.h>
> > +#include <assert.h>
> > +#include <signal.h>
> > +#include <fcntl.h>
> > +#include <time.h>
> > +
> > +#include "intel_dp_compliance.h"
> > +
> > +#include <stdlib.h>
> > +#include <signal.h>
> > +
> > +/* User Input definitions */
> > +#define HELP_DESCRIPTION 1
> > +
> > +/* Debugfs file definitions */
> > +#define INTEL_DP_TEST_TYPE_FILE                "i915_dp_test_type"
> > +#define INTEL_DP_TEST_ACTIVE_FILE      "i915_dp_test_active"
> > +#define INTEL_DP_TEST_DATA_FILE                "i915_dp_test_data"
> > +
> > +/* DRM definitions - must be kept in sync with the DRM header */
> > +#define DP_TEST_LINK_TRAINING          (1 << 0)
> > +#define DP_TEST_LINK_VIDEO_PATTERN     (1 << 1)
> > +#define DP_TEST_LINK_EDID_READ         (1 << 2)
> > +#define DP_TEST_LINK_PHY_TEST_PATTERN  (1 << 3) /* DPCD >= 1.1 */
> > +
> > +#define DP_COMPLIANCE_TEST_TYPE_MASK   (DP_TEST_LINK_TRAINING      |   \
> > +                                        DP_TEST_LINK_VIDEO_PATTERN |   \
> > +                                        DP_TEST_LINK_EDID_READ     |   \
> > +                                        DP_TEST_LINK_PHY_TEST_PATTERN)
> > +
> > +/* NOTE: These must be kept in sync with the definitions in intel_dp.c */
> > +#define INTEL_DP_EDID_SHIFT_MASK       0
> > +#define INTEL_DP_EDID_OK               (0 << INTEL_DP_EDID_SHIFT_MASK)
> > +#define INTEL_DP_EDID_CORRUPT          (1 << INTEL_DP_EDID_SHIFT_MASK)
> > +#define INTEL_DP_RESOLUTION_SHIFT_MASK 0
> > +#define INTEL_DP_RESOLUTION_PREFERRED  (1 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> > +#define INTEL_DP_RESOLUTION_STANDARD   (2 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> > +#define INTEL_DP_RESOLUTION_FAILSAFE   (3 << INTEL_DP_RESOLUTION_SHIFT_MASK)
> > +#define DP_COMPLIANCE_VIDEO_MODE_MASK  (INTEL_DP_RESOLUTION_PREFERRED  |\
> > +                                        INTEL_DP_RESOLUTION_STANDARD   |\
> > +                                        INTEL_DP_RESOLUTION_FAILSAFE)
> > +
> > +/* Global file pointers for the sysfs files */
> > +FILE *test_active_fp, *test_data_fp, *test_type_fp;
> > +
> > +bool video_pattern_flag;
> > +
> > +/* Video pattern test globals */
> > +uint16_t hdisplay;
> > +uint16_t vdisplay;
> > +uint8_t bitdepth;
> > +
> > +static int tio_fd;
> > +struct termios saved_tio;
> > +
> > +drmModeRes *resources;
> > +int drm_fd, modes;
> > +uint64_t tiling = LOCAL_DRM_FORMAT_MOD_NONE;
> > +uint32_t depth = 24, stride, bpp;
> > +int specified_mode_num = -1, specified_disp_id = -1;
> > +int width, height;
> > +uint32_t test_crtc;
> > +uint32_t test_connector_id;
> > +enum {
> > +       INTEL_MODE_INVALID = -1,
> > +       INTEL_MODE_NONE = 0,
> > +       INTEL_MODE_PREFERRED,
> > +       INTEL_MODE_STANDARD,
> > +       INTEL_MODE_FAILSAFE,
> > +       INTEL_MODE_VIDEO_PATTERN_TEST
> > +} intel_display_mode;
> > +
> > +struct test_video_pattern {
> > +       uint16_t hdisplay;
> > +       uint16_t vdisplay;
> > +       uint8_t bitdepth;
> > +       uint32_t fb;
> > +       uint32_t size;
> > +       struct igt_fb fb_pattern;
> > +       drmModeModeInfo mode;
> > +       uint32_t *pixmap;
> > +};
> > +
> > +struct connector {
> > +       uint32_t id;
> > +       int mode_valid;
> > +       drmModeModeInfo mode, mode_standard, mode_preferred, mode_failsafe;
> > +       drmModeConnector *connector;
> > +       int crtc;
> > +       /* Standard and preferred frame buffer*/
> > +       uint32_t fb, fb_width, fb_height, fb_size;
> > +       uint8_t *pixmap;
> > +       struct igt_fb fb_video_pattern;
> > +       /* Failsafe framebuffer - note this is a 16-bit buffer */
> > +       uint32_t failsafe_fb, failsafe_width, failsafe_height;
> > +       uint32_t failsafe_size;
> > +       uint8_t *failsafe_pixmap;
> > +       struct igt_fb fb_failsafe_pattern;
> > +       struct test_video_pattern test_pattern;
> > +};
> > +
> > +static void clear_test_active(void)
> > +{
> > +       rewind(test_active_fp);
> > +       fprintf(test_active_fp, "%d", 0);
> > +       fflush(test_active_fp);
> > +}
> > +
> > +static void setup_debugfs_files(void)
> > +{
> > +       test_type_fp = igt_debugfs_fopen(INTEL_DP_TEST_TYPE_FILE, "r");
> > +       igt_require(test_type_fp);
> > +
> > +       test_data_fp = igt_debugfs_fopen(INTEL_DP_TEST_DATA_FILE, "r");
> > +       igt_require(test_data_fp);
> > +
> > +       test_active_fp = igt_debugfs_fopen(INTEL_DP_TEST_ACTIVE_FILE, "w+");
> > +       igt_require(test_active_fp);
> > +
> > +       /* Reset the active flag for safety */
> > +       clear_test_active();
> > +}
> > +
> > +static unsigned long get_test_type(void)
> > +{
> > +       unsigned long test_type;
> > +       int ret;
> > +
> > +       if (!test_type_fp)
> > +               fprintf(stderr, "Invalid test_type file\r\n");
> > +       rewind(test_type_fp);
> > +       ret = fscanf(test_type_fp, "%02lx", &test_type);
> > +       if (ret < 1 || test_type <= 0) {
> > +               igt_warn("test_type read failed - %02lx\r\n", test_type);
> > +               return 0;
> > +       }
> > +
> > +       return test_type;
> > +}
> > +
> > +static unsigned long get_test_edid_data(void)
> > +{
> > +       unsigned long test_data;
> > +       int ret;
> > +
> > +       if (!test_data_fp)
> > +               fprintf(stderr, "Invalid test_data file\r\n");
> > +
> > +       rewind(test_data_fp);
> > +       ret = fscanf(test_data_fp, "%lx", &test_data);
> > +       if (ret < 1 || test_data <= 0) {
> > +               igt_warn("test_data read failed - %lx\r\n", test_data);
> > +               return 0;
> > +       }
> > +
> > +       return test_data;
> > +}
> > +
> > +static void get_test_videopattern_data(void)
> > +{
> > +       int count = 0;
> > +       uint16_t video_pattern_value[3];
> > +       char video_pattern_attribute[15];
> > +       int ret;
> > +
> > +       if (!test_data_fp)
> > +               fprintf(stderr, "Invalid test_data file\r\n");
> > +
> > +       rewind(test_data_fp);
> > +       while (!feof(test_data_fp) && count < 3) {
> > +               ret = fscanf(test_data_fp, "%s %u\n", video_pattern_attribute,
> > +                      (unsigned int *)&video_pattern_value[count++]);
> > +               if (ret < 2) {
> > +                       igt_warn("test_data read failed\n");
> > +                       return;
> > +               }
> > +       }
> > +
> > +       hdisplay = video_pattern_value[0];
> > +       vdisplay = video_pattern_value[1];
> > +       bitdepth = video_pattern_value[2];
> > +       igt_info("Hdisplay = %d\r\n", hdisplay);
> > +       igt_info("Vdisplay = %d\r\n", vdisplay);
> > +       igt_info("BitDepth = %u\r\n", bitdepth);
> > +
> > +}
> > +
> > +static int process_test_request(int test_type)
> > +{
> > +       int mode;
> > +       unsigned long test_data_edid;
> > +       bool valid = false;
> > +       switch (test_type) {
> > +       case DP_TEST_LINK_VIDEO_PATTERN:
> > +               video_pattern_flag = true;
> > +               get_test_videopattern_data();
> > +               mode = INTEL_MODE_VIDEO_PATTERN_TEST;
> > +               valid = true;
> > +               break;
> > +       case DP_TEST_LINK_EDID_READ:
> > +               test_data_edid = get_test_edid_data();
> > +               mode = (test_data_edid & DP_COMPLIANCE_VIDEO_MODE_MASK) >>
> > +                       INTEL_DP_RESOLUTION_SHIFT_MASK;
> > +               valid = true;
> > +               break;
> > +       default:
> > +               /* Unknown test type */
> > +               fprintf(stderr, "Invalid test request, ignored.\r\n");
> > +               break;
> > +       }
> > +
> > +       if (valid)
> > +               return update_display(mode, true);
> > +
> > +       return -1;
> > +}
> > +
> > +static void dump_connectors_fd(int drmfd)
> > +{
> > +       int i, j;
> > +
> > +       drmModeRes *mode_resources = drmModeGetResources(drmfd);
> > +
> > +       if (!mode_resources) {
> > +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> > +               return;
> > +       }
> > +
> > +       igt_info("Connectors:\n");
> > +       igt_info("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
> > +       for (i = 0; i < mode_resources->count_connectors; i++) {
> > +               drmModeConnector *connector;
> > +
> > +               connector = drmModeGetConnectorCurrent(drmfd,
> > +                                                      mode_resources->connectors[i]);
> > +               if (!connector) {
> > +                       igt_warn("Could not get connector %i: %s\n",
> > +                                mode_resources->connectors[i], strerror(errno));
> > +                       continue;
> > +               }
> > +
> > +               igt_info("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
> > +                        connector->connector_id,
> > +                        connector->encoder_id,
> > +                        kmstest_connector_status_str(connector->connection),
> > +                        kmstest_connector_type_str(connector->connector_type),
> > +                        connector->mmWidth,
> > +                        connector->mmHeight,
> > +                        connector->count_modes);
> > +
> > +               if (!connector->count_modes)
> > +                       continue;
> > +
> > +               igt_info("  Modes:\n");
> > +               igt_info("  name refresh (Hz) hdisp hss hse htot vdisp ""vss vse vtot flags type clock\n");
> > +               for (j = 0; j < connector->count_modes; j++) {
> > +                       igt_info("[%d]", j);
> > +                       kmstest_dump_mode(&connector->modes[j]);
> > +               }
> > +
> > +               drmModeFreeConnector(connector);
> > +       }
> > +       igt_info("\n");
> > +
> > +       drmModeFreeResources(mode_resources);
> > +}
> > +
> > +static void dump_crtcs_fd(int drmfd)
> > +{
> > +       int i;
> > +       drmModeRes *mode_resources;
> > +
> > +       mode_resources = drmModeGetResources(drmfd);
> > +       if (!mode_resources) {
> > +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> > +               return;
> > +       }
> > +
> > +       igt_info("CRTCs:\n");
> > +       igt_info("id\tfb\tpos\tsize\n");
> > +       for (i = 0; i < mode_resources->count_crtcs; i++) {
> > +               drmModeCrtc *crtc;
> > +
> > +               crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]);
> > +               if (!crtc) {
> > +                       igt_warn("Could not get crtc %i: %s\n", mode_resources->crtcs[i], strerror(errno));
> > +                       continue;
> > +               }
> > +               igt_info("%d\t%d\t(%d,%d)\t(%dx%d)\n",
> > +                        crtc->crtc_id,
> > +                        crtc->buffer_id,
> > +                        crtc->x,
> > +                        crtc->y,
> > +                        crtc->width,
> > +                        crtc->height);
> > +
> > +               kmstest_dump_mode(&crtc->mode);
> > +
> > +               drmModeFreeCrtc(crtc);
> > +       }
> > +       igt_info("\n");
> > +
> > +       drmModeFreeResources(mode_resources);
> > +}
> > +
> > +static void dump_info(void)
> > +{
> > +       dump_connectors_fd(drm_fd);
> > +       dump_crtcs_fd(drm_fd);
> > +}
> > +
> > +static int setup_framebuffers(struct connector *dp_conn)
> > +{
> > +
> > +       dp_conn->fb = igt_create_fb(drm_fd,
> > +                                   dp_conn->fb_width, dp_conn->fb_height,
> > +                                   DRM_FORMAT_XRGB8888,
> > +                                   LOCAL_DRM_FORMAT_MOD_NONE,
> > +                                   &dp_conn->fb_video_pattern);
> > +       igt_assert(dp_conn->fb);
> > +
> > +       /* Map the mapping of GEM object into the virtual address space */
> > +       dp_conn->pixmap = gem_mmap__gtt(drm_fd,
> > +                                       dp_conn->fb_video_pattern.gem_handle,
> > +                                       dp_conn->fb_video_pattern.size,
> > +                                       PROT_READ | PROT_WRITE);
> > +       if (dp_conn->pixmap == NULL)
> > +               return -1;
> > +
> > +       gem_set_domain(drm_fd, dp_conn->fb_video_pattern.gem_handle,
> > +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +       dp_conn->fb_size = dp_conn->fb_video_pattern.size;
> > +
> > +       /* After filling the device memory with 0s it needs to be unmapped */
> > +       memset(dp_conn->pixmap, 0, dp_conn->fb_size);
> > +       munmap(dp_conn->pixmap, dp_conn->fb_size);
> > +
> > +       return 0;
> > +}
> > +
> > +static int setup_failsafe_framebuffer(struct connector *dp_conn)
> > +{
> > +
> > +       dp_conn->failsafe_fb = igt_create_fb(drm_fd,
> > +                                            dp_conn->failsafe_width,
> > +                                            dp_conn->failsafe_height,
> > +                                            DRM_FORMAT_XRGB8888,
> > +                                            LOCAL_DRM_FORMAT_MOD_NONE,
> > +                                            &dp_conn->fb_failsafe_pattern);
> > +       igt_assert(dp_conn->failsafe_fb);
> > +
> > +       /* Map the mapping of GEM object into the virtual address space */
> > +       dp_conn->failsafe_pixmap = gem_mmap__gtt(drm_fd,
> > +                                                dp_conn->fb_failsafe_pattern.gem_handle,
> > +                                                dp_conn->fb_failsafe_pattern.size,
> > +                                                PROT_READ | PROT_WRITE);
> > +       if (dp_conn->failsafe_pixmap == NULL)
> > +               return -1;
> > +
> > +       gem_set_domain(drm_fd, dp_conn->fb_failsafe_pattern.gem_handle,
> > +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +       dp_conn->failsafe_size = dp_conn->fb_failsafe_pattern.size;
> > +
> > +       /* After filling the device framebuffer the mapped memory needs to be freed */
> > +       memset(dp_conn->failsafe_pixmap, 0, dp_conn->failsafe_size);
> > +       munmap(dp_conn->failsafe_pixmap, dp_conn->failsafe_size);
> > +
> > +       return 0;
> > +
> > +}
> > +
> > +static int setup_video_pattern_framebuffer(struct connector *dp_conn)
> > +{
> > +       uint32_t  video_width, video_height;
> > +
> > +       video_width = dp_conn->test_pattern.hdisplay;
> > +       video_height = dp_conn->test_pattern.vdisplay;
> > +       dp_conn->test_pattern.fb = igt_create_fb(drm_fd,
> > +                                                video_width, video_height,
> > +                                                DRM_FORMAT_XRGB8888,
> > +                                                LOCAL_DRM_FORMAT_MOD_NONE,
> > +                                                &dp_conn->test_pattern.fb_pattern);
> > +       igt_assert(dp_conn->test_pattern.fb);
> > +
> > +       /* Map the mapping of GEM object into the virtual address space */
> > +       dp_conn->test_pattern.pixmap = gem_mmap__gtt(drm_fd,
> > +                                                    dp_conn->test_pattern.fb_pattern.gem_handle,
> > +                                                    dp_conn->test_pattern.fb_pattern.size,
> > +                                                    PROT_READ | PROT_WRITE);
> > +       if (dp_conn->test_pattern.pixmap == NULL)
> > +               return -1;
> > +
> > +       gem_set_domain(drm_fd, dp_conn->test_pattern.fb_pattern.gem_handle,
> > +                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
> > +
> > +       dp_conn->test_pattern.size = dp_conn->test_pattern.fb_pattern.size;
> > +
> > +       memset(dp_conn->test_pattern.pixmap, 0, dp_conn->test_pattern.size);
> > +       return 0;
> > +
> > +}
> > +
> > +static int fill_framebuffer(struct connector *dp_conn)
> > +{
> > +       uint32_t tile_height, tile_width, video_width, video_height;
> > +       uint32_t *red_ptr, *green_ptr, *blue_ptr, *white_ptr, *src_ptr, *dst_ptr;
> > +       int x, y;
> > +       int32_t pixel_val;
> > +
> > +       video_width = dp_conn->test_pattern.hdisplay;
> > +       video_height = dp_conn->test_pattern.vdisplay;
> > +
> > +       tile_height = 64;
> > +       tile_width = 1 <<  (dp_conn->test_pattern.bitdepth);
> > +
> > +       red_ptr = dp_conn->test_pattern.pixmap;
> > +       green_ptr = red_ptr + (video_width * tile_height);
> > +       blue_ptr = green_ptr + (video_width * tile_height);
> > +       white_ptr = blue_ptr + (video_width * tile_height);
> > +       x = 0;
> > +
> > +       /* Fill the frame buffer with video pattern from CTS 3.1.5 */
> > +       while (x < video_width) {
> > +               for (pixel_val = 0; pixel_val < 256;
> > +                    pixel_val = pixel_val + (256 / tile_width)) {
> > +                       red_ptr[x] = pixel_val << 16;
> > +                       green_ptr[x] = pixel_val << 8;
> > +                       blue_ptr[x] = pixel_val << 0;
> > +                       white_ptr[x] = red_ptr[x] | green_ptr[x] | blue_ptr[x];
> > +                       if (++x >= video_width)
> > +                               break;
> > +               }
> > +       }
> > +       for (y = 0; y < video_height; y++) {
> > +               if (y == 0 || y == 64 || y == 128 || y == 192)
> > +                       continue;
> > +               switch ((y / tile_height) % 4) {
> > +               case 0:
> > +                       src_ptr = red_ptr;
> > +                       break;
> > +               case 1:
> > +                       src_ptr = green_ptr;
> > +                       break;
> > +               case 2:
> > +                       src_ptr = blue_ptr;
> > +                       break;
> > +               case 3:
> > +                       src_ptr = white_ptr;
> > +                       break;
> > +               }
> > +               dst_ptr = dp_conn->test_pattern.pixmap + (y * video_width);
> > +               memcpy(dst_ptr, src_ptr, (video_width * 4));
> > +       }
> > +       munmap(dp_conn->test_pattern.pixmap,
> > +              dp_conn->test_pattern.size);
> > +       return 0;
> > +}
> > +
> > +static int set_test_mode(struct connector *dp_conn)
> > +{
> > +       int ret = 0;
> > +       int i;
> > +       bool found_std = false, found_fs = false;
> > +       drmModeConnector *c = dp_conn->connector;
> > +
> > +       /* Ignore any disconnected devices */
> > +       if (c->connection != DRM_MODE_CONNECTED) {
> > +               igt_warn("Connector %u disconnected\r\n", c->connector_id);
> > +               return -ENOENT;
> > +       }
> > +       igt_info("Connector setup:\r\n");
> > +       /* Setup preferred mode - should be mode[0] in the list */
> > +       dp_conn->mode_preferred = c->modes[0];
> > +       dp_conn->fb_width = c->modes[0].hdisplay;
> > +       dp_conn->fb_height = c->modes[0].vdisplay;
> > +
> > +       dp_conn->test_pattern.mode = c->modes[0];
> > +       dp_conn->test_pattern.mode.hdisplay = c->modes[0].hdisplay;
> > +       dp_conn->test_pattern.mode.vdisplay = c->modes[0].vdisplay;
> > +
> > +       igt_info("Preferred mode (mode 0) for connector %u is %ux%u\r\n",
> > +                dp_conn->id, c->modes[0].hdisplay, c->modes[0].vdisplay);
> > +       fflush(stdin);
> > +
> > +       for (i = 1; i < c->count_modes; i++) {
> > +               /* Standard mode is 800x600@60 */
> > +               if (c->modes[i].hdisplay == 800 &&
> > +                   c->modes[i].vdisplay == 600 &&
> > +                   c->modes[i].vrefresh == 60 &&
> > +                   found_std == false) {
> > +                       dp_conn->mode_standard = c->modes[i];
> > +                       igt_info("Standard mode (%d) for connector %u is %ux%u\r\n",
> > +                                i,
> > +                                c->connector_id,
> > +                                c->modes[i].hdisplay,
> > +                                c->modes[i].vdisplay);
> > +                       found_std = true;
> > +               }
> > +               /* Failsafe mode is 640x480@60 */
> > +               if (c->modes[i].hdisplay == 640 &&
> > +                   c->modes[i].vdisplay == 480 &&
> > +                   c->modes[i].vrefresh == 60 &&
> > +                   found_fs == false) {
> > +                       dp_conn->mode_failsafe = c->modes[i];
> > +                       dp_conn->failsafe_width = c->modes[i].hdisplay;
> > +                       dp_conn->failsafe_height = c->modes[i].vdisplay;
> > +                       igt_info("Failsafe mode (%d) for connector %u is %ux%u\r\n",
> > +                                i,
> > +                                c->connector_id,
> > +                                c->modes[i].hdisplay,
> > +                                c->modes[i].vdisplay);
> > +                       found_fs = true;
> > +               }
> > +       }
> > +
> > +       ret = setup_framebuffers(dp_conn);
> > +       if (ret) {
> > +               igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
> > +                        c->connector_id, ret);
> > +               return ret;
> > +       }
> > +
> > +       if (found_fs) {
> > +               ret = setup_failsafe_framebuffer(dp_conn);
> > +               if (ret) {
> > +                       igt_warn("Creating failsafe framebuffer for connector %u failed (%d)\r\n",
> > +                                c->connector_id, ret);
> > +                       return ret;
> > +               }
> > +       }
> > +
> > +       if (video_pattern_flag) {
> > +               dp_conn->test_pattern.hdisplay = hdisplay;
> > +               dp_conn->test_pattern.vdisplay = vdisplay;
> > +               dp_conn->test_pattern.bitdepth = bitdepth;
> > +
> > +               ret = setup_video_pattern_framebuffer(dp_conn);
> > +               if (ret) {
> > +                       igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
> > +                                c->connector_id, ret);
> > +                       return ret;
> > +               }
> > +
> > +               ret = fill_framebuffer(dp_conn);
> > +               if (ret) {
> > +                       igt_warn("Filling framebuffer for connector %u failed (%d)\r\n",
> > +                                c->connector_id, ret);
> > +                       return ret;
> > +               }
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int set_video(int mode, struct connector *test_connector)
> > +{
> > +       drmModeModeInfo *requested_mode;
> > +       uint32_t required_fb_id;
> > +       struct igt_fb required_fb;
> > +       int ret = 0;
> > +
> > +       switch (mode) {
> > +       case INTEL_MODE_NONE:
> > +               igt_info("NONE\r\n");
> > +               ret = drmModeSetCrtc(drm_fd, test_connector->crtc,
> > +                                    -1, 0, 0, NULL, 0, NULL);
> > +               goto out;
> > +       case INTEL_MODE_PREFERRED:
> > +               igt_info("PREFERRED\r\n");
> > +               requested_mode =  &test_connector->mode_preferred;
> > +               required_fb_id = test_connector->fb;
> > +               required_fb = test_connector->fb_video_pattern;
> > +               break;
> > +       case INTEL_MODE_STANDARD:
> > +               igt_info("STANDARD\r\n");
> > +               requested_mode =  &test_connector->mode_standard;
> > +               required_fb_id = test_connector->fb;
> > +               required_fb = test_connector->fb_video_pattern;
> > +               break;
> > +       case INTEL_MODE_FAILSAFE:
> > +               igt_info("FAILSAFE\r\n");
> > +               requested_mode =  &test_connector->mode_failsafe;
> > +               required_fb_id = test_connector->failsafe_fb;
> > +               required_fb = test_connector->fb_failsafe_pattern;
> > +               break;
> > +       case INTEL_MODE_VIDEO_PATTERN_TEST:
> > +               igt_info("VIDEO PATTERN TEST\r\n");
> > +               requested_mode = &test_connector->test_pattern.mode;
> > +               required_fb_id = test_connector->test_pattern.fb;
> > +               required_fb = test_connector->test_pattern.fb_pattern;
> > +               break;
> > +       case INTEL_MODE_INVALID:
> > +       default:
> > +               igt_warn("INVALID! (%08x) Mode set aborted!\r\n", mode);
> > +               return -1;
> > +       }
> > +
> > +       igt_info("CRTC(%u):", test_connector->crtc);
> > +       kmstest_dump_mode(requested_mode);
> > +       ret = drmModeSetCrtc(drm_fd, test_connector->crtc, required_fb_id, 0, 0,
> > +                            &test_connector->id, 1, requested_mode);
> > +       if (ret) {
> > +               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
> > +                        requested_mode->hdisplay, requested_mode->vdisplay,
> > +                        requested_mode->vrefresh, strerror(errno));
> > +               igt_remove_fb(drm_fd, &required_fb);
> > +
> > +       }
> > +       /* Keep the pattern on output lines for 1 sec for DPR-120 to detect it */
> > +       sleep(1);
> > +
> > +out:
> > +       if (ret) {
> > +               igt_warn("Failed to set CRTC for connector %u\r\n",
> > +                        test_connector->id);
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static int
> > +set_default_mode(struct connector *c, bool set_mode)
> > +{
> > +       unsigned int fb_id = 0;
> > +       struct igt_fb fb_info;
> > +       int ret = 0;
> > +
> > +       if (!set_mode) {
> > +               ret = drmModeSetCrtc(drm_fd, c->crtc, 0, 0, 0,
> > +                                    NULL, 0, NULL);
> > +               if (ret)
> > +                       igt_warn("Failed to unset mode");
> > +               return ret;
> > +       }
> > +
> > +       c->mode = c->connector->modes[0];
> > +
> > +       width = c->mode.hdisplay;
> > +       height = c->mode.vdisplay;
> > +
> > +       fb_id = igt_create_pattern_fb(drm_fd, width, height,
> > +                                     DRM_FORMAT_XRGB8888,
> > +                                     tiling, &fb_info);
> > +
> > +       igt_info("CRTC(%u):[%d]", c->crtc, 0);
> > +       kmstest_dump_mode(&c->mode);
> > +       drmModeSetCrtc(drm_fd, c->crtc, -1, 0, 0, NULL, 0, NULL);
> > +       ret = drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
> > +                            &c->id, 1, &c->mode);
> > +       if (ret) {
> > +               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
> > +                        width, height, c->mode.vrefresh, strerror(errno));
> > +               igt_remove_fb(drm_fd, &fb_info);
> > +
> > +       }
> > +
> > +       return ret;
> > +}
> > +
> > +static uint32_t find_crtc_for_connector(drmModeConnector *c)
> > +{
> > +       drmModeEncoder *e;
> > +       uint32_t possible_crtcs;
> > +       int i, j;
> > +
> > +       for (i = 0; i < c->count_encoders; i++) {
> > +               e = drmModeGetEncoder(drm_fd, c->encoders[i]);
> > +               possible_crtcs = e->possible_crtcs;
> > +               drmModeFreeEncoder(e);
> > +
> > +               for (j = 0; possible_crtcs >> j; j++)
> > +                       if (possible_crtcs & (1 << j))
> > +                               return resources->crtcs[j];
> > +       }
> > +       return 0;
> > +}
> > +
> > +/*
> > + * Re-probe connectors and do a modeset based on test request or
> > + * in case of a hotplug uevent.
> > + *
> > + * @mode: Video mode requested by the test
> > + * @is_compliance_test: 1: If it is a compliance test
> > + *                      0: If it is a hotplug event
> > + *
> > + * Returns:
> > + * 0: On Success
> > + * -1: On failure
> > + */
> > +int update_display(int mode, bool is_compliance_test)
> > +{
> > +       struct connector *connectors, *conn;
> > +       int cnt, ret = 0;
> > +       bool set_mode;
> > +
> > +       resources = drmModeGetResources(drm_fd);
> > +       if (!resources) {
> > +               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
> > +               return -1;
> > +       }
> > +
> > +       connectors = calloc(resources->count_connectors,
> > +                           sizeof(struct connector));
> > +       if (!connectors)
> > +               return -1;
> > +
> > +       /* Find any connected displays */
> > +       for (cnt = 0; cnt < resources->count_connectors; cnt++) {
> > +               drmModeConnector *c;
> > +
> > +               conn = &connectors[cnt];
> > +               conn->id = resources->connectors[cnt];
> > +               c = drmModeGetConnector(drm_fd, conn->id);
> > +               if (c->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
> > +                   c->connection == DRM_MODE_CONNECTED) {
> > +                       test_connector_id = c->connector_id;
> > +                       conn->connector = c;
> > +                       conn->crtc = find_crtc_for_connector(c);
> > +                       test_crtc = conn->crtc;
> > +                       set_mode = true;
> > +                       break;
> > +               } else if (c->connector_id == test_connector_id &&
> > +                          c->connection == DRM_MODE_DISCONNECTED) {
> > +                       conn->connector = c;
> > +                       conn->crtc = test_crtc;
> > +                       set_mode = false;
> > +                       break;
> > +               }
> > +       }
> > +
> > +       if (cnt == resources->count_connectors) {
> > +               ret = -1;
> > +               goto err;
> > +       }
> > +
> > +       if (is_compliance_test) {
> > +               set_test_mode(conn);
> > +               ret = set_video(INTEL_MODE_NONE, conn);
> > +               ret = set_video(mode, conn);
> > +
> > +       } else
> > +               ret = set_default_mode(conn, set_mode);
> > +
> > + err:
> > +       drmModeFreeConnector(conn->connector);
> > +       /* Error condition if no connected displays */
> > +       free(connectors);
> > +       drmModeFreeResources(resources);
> > +       return ret;
> > +}
> > +
> > +static const char optstr[] = "hi";
> > +
> > +static void __attribute__((noreturn)) usage(char *name, char opt)
> > +{
> > +       igt_info("usage: %s [-hi]\n", name);
> > +       igt_info("\t-i\tdump info\n");
> > +       igt_info("\tDefault is to respond to DPR-120 tests\n");
> > +       exit((opt != 'h') ? -1 : 0);
> > +}
> > +
> > +static void cleanup_debugfs(void)
> > +{
> > +       fclose(test_active_fp);
> > +       fclose(test_data_fp);
> > +       fclose(test_type_fp);
> > +}
> > +
> > +static void __attribute__((noreturn)) cleanup_and_exit(int ret)
> > +{
> > +       cleanup_debugfs();
> > +       close(drm_fd);
> > +       igt_info("Compliance testing application exiting\n");
> > +       exit(ret);
> > +}
> > +
> > +static void cleanup_test(void)
> > +{
> > +       video_pattern_flag = false;
> > +       hdisplay = 0;
> > +       vdisplay = 0;
> > +       bitdepth = 0;
> > +}
> > +
> > +static void read_test_request(void)
> > +{
> > +       unsigned long test_type;
> > +
> > +       test_type = get_test_type();
> > +       process_test_request(test_type);
> > +       cleanup_test();
> > +       clear_test_active();
> > +}
> > +
> > +static gboolean test_handler(GIOChannel *source, GIOCondition condition,
> > +                            gpointer data)
> > +{
> > +       unsigned long test_active;
> > +       int ret;
> > +
> > +       rewind(test_active_fp);
> > +
> > +       ret = fscanf(test_active_fp, "%lx", &test_active);
> > +       if (ret < 1)
> > +               return FALSE;
> > +
> > +       if (test_active)
> > +               read_test_request();
> > +       return TRUE;
> > +}
> > +
> > +static gboolean input_event(GIOChannel *source, GIOCondition condition,
> > +                               gpointer data)
> > +{
> > +       gchar buf[2];
> > +       gsize count;
> > +
> > +       count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf));
> > +       if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) {
> > +               cleanup_and_exit(0);
> > +       }
> > +
> > +       return TRUE;
> > +}
> > +
> > +static void enter_exec_path(char **argv)
> > +{
> > +       char *exec_path = NULL;
> > +       char *pos = NULL;
> > +       short len_path = 0;
> > +       int ret;
> > +
> > +       len_path = strlen(argv[0]);
> > +       exec_path = (char *) malloc(len_path);
> > +
> > +       memcpy(exec_path, argv[0], len_path);
> > +       pos = strrchr(exec_path, '/');
> > +       if (pos != NULL)
> > +               *(pos+1) = '\0';
> > +
> > +       ret = chdir(exec_path);
> > +       igt_assert_eq(ret, 0);
> > +       free(exec_path);
> > +}
> > +
> > +static void restore_termio_mode(int sig)
> > +{
> > +       tcsetattr(tio_fd, TCSANOW, &saved_tio);
> > +       close(tio_fd);
> > +}
> > +
> > +static void set_termio_mode(void)
> > +{
> > +       struct termios tio;
> > +
> > +       /* don't attempt to set terminal attributes if not in the foreground
> > +        * process group
> > +        */
> > +       if (getpgrp() != tcgetpgrp(STDOUT_FILENO))
> > +               return;
> > +
> > +       tio_fd = dup(STDIN_FILENO);
> > +       tcgetattr(tio_fd, &saved_tio);
> > +       igt_install_exit_handler(restore_termio_mode);
> > +       tio = saved_tio;
> > +       tio.c_lflag &= ~(ICANON | ECHO);
> > +       tcsetattr(tio_fd, TCSANOW, &tio);
> > +}
> > +
> > +int main(int argc, char **argv)
> > +{
> > +       int c;
> > +       int ret = 0;
> > +       GIOChannel *stdinchannel, *testactive_channel;
> > +       GMainLoop *mainloop;
> > +       bool opt_dump_info = false;
> > +       struct option long_opts[] = {
> > +               {"help-description", 0, 0, HELP_DESCRIPTION},
> > +               {"help", 0, 0, 'h'},
> > +       };
> > +
> > +       igt_skip_on_simulation();
> > +
> > +       enter_exec_path(argv);
> > +
> > +       while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) {
> > +               switch (c) {
> > +               case 'i':
> > +                       opt_dump_info = true;
> > +                       break;
> > +               case HELP_DESCRIPTION:
> > +                       igt_info("DP Compliance Test Suite using DPR-120\n");
> > +                       igt_info("EDID tests\n");
> > +                       igt_info("Video Pattern Generation tests\n");
> > +                       exit(0);
> > +                       break;
> > +               default:
> > +                       /* fall through */
> > +               case 'h':
> > +                       usage(argv[0], c);
> > +                       break;
> > +               }
> > +       }
> > +
> > +       set_termio_mode();
> > +
> > +       igt_info("*************DP Compliance Testing using DPR-120*************\n");
> > +       igt_info("Waiting for test request......\n");
> > +       drm_fd = drm_open_driver(DRIVER_ANY);
> > +
> > +       kmstest_set_vt_graphics_mode();
> > +       setup_debugfs_files();
> > +       cleanup_test();
> > +
> > +       if (opt_dump_info) {
> > +               dump_info();
> > +               goto out_close;
> > +       }
> > +
> > +       /* Get the DP connector ID and CRTC */
> > +       if (update_display(0, false)) {
> > +               igt_warn("Failed to set default mode\n");
> > +               ret = -1;
> > +               goto out_close;
> > +       }
> > +
> > +       mainloop = g_main_loop_new(NULL, FALSE);
> > +       if (!mainloop) {
> > +               igt_warn("Failed to create GMainLoop\n");
> > +               ret = -1;
> > +               goto out_close;
> > +       }
> > +
> > +       if (!intel_dp_compliance_setup_hotplug()) {
> > +               igt_warn("Failed to initialize hotplug support\n");
> > +               goto out_mainloop;
> > +       }
> > +
> > +       testactive_channel = g_io_channel_unix_new(fileno(test_active_fp));
> > +       if (!testactive_channel) {
> > +               igt_warn("Failed to create test_active GIOChannel\n");
> > +               goto out_close;
> > +       }
> > +
> > +       ret = g_io_add_watch(testactive_channel, G_IO_IN | G_IO_ERR,
> > +                            test_handler, NULL);
> > +       if (ret < 0) {
> > +               igt_warn("Failed to add watch on udev GIOChannel\n");
> > +               goto out_close;
> > +       }
> > +
> > +       stdinchannel = g_io_channel_unix_new(0);
> > +       if (!stdinchannel) {
> > +               igt_warn("Failed to create stdin GIOChannel\n");
> > +               goto out_hotplug;
> > +       }
> > +
> > +       ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event,
> > +                            NULL);
> > +       if (ret < 0) {
> > +               igt_warn("Failed to add watch on stdin GIOChannel\n");
> > +               goto out_stdio;
> > +       }
> > +
> > +       ret = 0;
> > +
> > +       g_main_loop_run(mainloop);
> > +
> > +out_stdio:
> > +       g_io_channel_shutdown(stdinchannel, TRUE, NULL);
> > +out_hotplug:
> > +       intel_dp_compliance_cleanup_hotplug();
> > +out_mainloop:
> > +       g_main_loop_unref(mainloop);
> > +out_close:
> > +       cleanup_debugfs();
> > +       close(drm_fd);
> > +
> > +       igt_assert_eq(ret, 0);
> > +
> > +       igt_info("Compliance testing application exiting\n");
> > +       igt_exit();
> > +}
> > diff --git a/tools/intel_dp_compliance.h b/tools/intel_dp_compliance.h
> > new file mode 100644
> > index 0000000..ade1e2f
> > --- /dev/null
> > +++ b/tools/intel_dp_compliance.h
> > @@ -0,0 +1,35 @@
> > +/*
> > + * Copyright 2010 Intel Corporation
> > + * Manasi Navare <manasi.d.navare@intel.com>
> > + *
> > + * 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 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 <stdio.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +#include <glib.h>
> > +
> > +extern int drm_fd;
> > +
> > +gboolean intel_dp_compliance_setup_hotplug(void);
> > +void intel_dp_compliance_cleanup_hotplug(void);
> > +
> > +/* called by the hotplug code */
> > +int update_display(int mode, bool is_compliance_test);
> > diff --git a/tools/intel_dp_compliance_hotplug.c b/tools/intel_dp_compliance_hotplug.c
> > new file mode 100644
> > index 0000000..7c7ea65
> > --- /dev/null
> > +++ b/tools/intel_dp_compliance_hotplug.c
> > @@ -0,0 +1,123 @@
> > +/*
> > + * Copyright 2010 Intel Corporation
> > + *   Jesse Barnes <jesse.barnes@intel.com>
> > + *
> > + * 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 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.h"
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +
> > +#include <sys/stat.h>
> > +
> > +#include "intel_dp_compliance.h"
> > +#include <libudev.h>
> > +static struct udev_monitor *uevent_monitor;
> > +static struct udev *udev;
> > +static GIOChannel *udevchannel;
> > +
> > +static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
> > +                             gpointer data)
> > +{
> > +       struct udev_device *dev;
> > +       dev_t udev_devnum;
> > +       struct stat s;
> > +       const char *hotplug;
> > +
> > +       dev = udev_monitor_receive_device(uevent_monitor);
> > +       if (!dev)
> > +               goto out;
> > +
> > +       udev_devnum = udev_device_get_devnum(dev);
> > +       fstat(drm_fd, &s);
> > +
> > +       hotplug = udev_device_get_property_value(dev, "HOTPLUG");
> > +
> > +       if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
> > +           hotplug && atoi(hotplug) == 1)
> > +               update_display(0, false);
> > +
> > +       udev_device_unref(dev);
> > +out:
> > +       return TRUE;
> > +}
> > +
> > +
> > +gboolean intel_dp_compliance_setup_hotplug(void)
> > +{
> > +       int ret;
> > +
> > +       udev = udev_new();
> > +       if (!udev) {
> > +               igt_warn("Failed to create udev object\n");
> > +               goto out;
> > +       }
> > +
> > +       uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
> > +       if (!uevent_monitor) {
> > +               igt_warn("Failed to create udev event monitor\n");
> > +               goto out;
> > +       }
> > +
> > +       ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
> > +                                                             "drm",
> > +                                                             "drm_minor");
> > +       if (ret < 0) {
> > +               igt_warn("Failed to filter for drm events\n");
> > +               goto out;
> > +       }
> > +
> > +       ret = udev_monitor_enable_receiving(uevent_monitor);
> > +       if (ret < 0) {
> > +               igt_warn("Failed to enable udev event reception\n");
> > +               goto out;
> > +       }
> > +
> > +       udevchannel =
> > +               g_io_channel_unix_new(udev_monitor_get_fd(uevent_monitor));
> > +       if (!udevchannel) {
> > +               igt_warn("Failed to create udev GIOChannel\n");
> > +               goto out;
> > +       }
> > +
> > +       ret = g_io_add_watch(udevchannel, G_IO_IN | G_IO_ERR, hotplug_event,
> > +                            udev);
> > +       if (ret < 0) {
> > +               igt_warn("Failed to add watch on udev GIOChannel\n");
> > +               goto out;
> > +       }
> > +
> > +       return TRUE;
> > +
> > +out:
> > +       intel_dp_compliance_cleanup_hotplug();
> > +       return FALSE;
> > +}
> > +
> > +void intel_dp_compliance_cleanup_hotplug(void)
> > +{
> > +       if (udevchannel)
> > +               g_io_channel_shutdown(udevchannel, TRUE, NULL);
> > +       if (uevent_monitor)
> > +               udev_monitor_unref(uevent_monitor);
> > +       if (udev)
> > +               udev_unref(udev);
> > +}
> > --
> > 2.7.4
> >
diff mbox

Patch

diff --git a/tools/Makefile.am b/tools/Makefile.am
index 18f86f6..bd8f512 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -16,6 +16,7 @@  AM_CFLAGS = $(DEBUG_CFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \
 LDADD = $(top_builddir)/lib/libintel_tools.la
 AM_LDFLAGS = -Wl,--as-needed

+intel_dp_compliance_LDADD = $(top_builddir)/lib/libintel_tools.la $(GLIB_LIBS)

 # aubdumper

diff --git a/tools/Makefile.sources b/tools/Makefile.sources
index e2451ea..e8ce891 100644
--- a/tools/Makefile.sources
+++ b/tools/Makefile.sources
@@ -13,6 +13,7 @@  tools_prog_lists =            \
        intel_bios_reader       \
        intel_display_crc       \
        intel_display_poller    \
+       intel_dp_compliance     \
        intel_forcewaked        \
        intel_gpu_frequency     \
        intel_firmware_decode   \
@@ -56,3 +57,9 @@  intel_l3_parity_SOURCES =     \
        intel_l3_parity.h       \
        intel_l3_udev_listener.c

+intel_dp_compliance_SOURCES = \
+        intel_dp_compliance.c \
+        intel_dp_compliance.h \
+        intel_dp_compliance_hotplug.c \
+        $(NULL)
+
diff --git a/tools/intel_dp_compliance.c b/tools/intel_dp_compliance.c
new file mode 100644
index 0000000..df1ca10
--- /dev/null
+++ b/tools/intel_dp_compliance.c
@@ -0,0 +1,1104 @@ 
+/*
+ * 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.
+ *
+ * Displayport Compliance Testing Application
+ *
+ * This is the userspace component of the Displayport Compliance testing
+ * software required for compliance testing of the I915 Display Port driver.
+ * This must be running in order to successfully complete Display Port
+ * compliance testing. This app and the kernel code that accompanies it has been
+ * written to satify the requirements of the Displayport Link CTS 1.2 rev1.1
+ * specification from VESA. Note that this application does not support eDP
+ * compliance testing.
+ *
+ * Compliance Testing requires several components:
+ *   - A kernel build that contains the patch set for DP compliance support
+ *   - A Displayport Compliance Testing appliance such as Unigraf-DPR120
+ *   - This user application
+ *   - A windows host machine to run the DPR test software
+ *   - Root access on the DUT due to the use of sysfs utility
+ *
+ * Test Setup:
+ * It is strongly recommended that the windows host, test appliance and DUT
+ * be freshly restarted before any testing begins to ensure that any previous
+ * configurations and settings will not interfere with test process. Refer to
+ * the test appliance documentation for setup, software installation and
+ * operation specific to that device.
+ *
+ * The Linux DUT must be in text (console) mode and cannot have any other
+ * display manager running. You must be logged in as root to run this user app.
+ * Once the user application is up and running, waiting for test requests, the
+ * software on the windows host can now be used to execute the compliance tests.
+ *
+ * This userspace application supports following tests from the DP CTS Spec
+ * Rev 1.1:
+ *   - Link Training Tests: Supports tests 4.3.1.1 to 4.3.2.3
+ *   - EDID Tests: Supports EDID read (4.2.2.3),EDID Read failure and corruption
+ *     detection tests (4.2.2.4, 4.2.2.5, 4.2.2.6)
+ *   - Video Pattern generation tests: This supports only the 24 and 18bpp color
+ *     ramp test pattern (4.3.3.1).
+ *
+ * Connections (required):
+ *   - Test Appliance connected to the external Displayport connector on the DUT
+ *   - Test Appliance Monitor Out connected to Displayport connector on the
+ * monitor
+ *   - Test appliance connected to the Windows Host via USB
+ *
+ * Debugfs Files:
+ * The file root for all  the debugfs file:
+ * /sys/kernel/debug/dri/0/
+ *
+ * The specific files are as follows:
+ *
+ * i915_dp_test_active
+ * A simple flag that indicates whether or not compliance testing is currently
+ * active in the kernel. This flag is polled by userspace and once set, invokes
+ * the test handler in the user app. This flag is set by the test handler in the
+ * kernel after reading the registers requested by the test appliance.
+ *
+ * i915_dp_test_data
+ * Test data is used by the kernel to pass parameters to the user app. Eg: In
+ * case of EDID tests, the data that is delivered to the userspace is the video
+ * mode to be set for the test.
+ * In case of video pattern test, the data that is delivered to the userspace is
+ * the width and height of the test pattern and the bits per color value.
+ *
+ * i915_dp_test_type
+ * The test type variable instructs the user app as to what the requested test
+ * was from the sink device. These values defined at the top of the application's
+ * main implementation file must be kept in sync with the values defined in the
+ * kernel's drm_dp_helper.h file.
+ * This app is based on some prior work submitted in April 2015 by Todd Previte
+ * (<tprevite@gmail.com>)
+ *
+ *
+ * This tool can be run as:
+ * ./intel_dp_compliance  It will wait till you start compliance suite from
+ * DPR 120.
+ * ./intel_dp_compliance -h  This will open the help
+ * ./intel_dp_compliance -i  This will provide information about current
+ * connectors/CRTCs. This can be used for debugging purpose.
+ *
+ * Authors:
+ *    Manasi Navare <manasi.d.navare@intel.com>
+ *
+ * Elements of the modeset code adapted from David Herrmann's
+ * DRM modeset example
+ *
+ */
+#include "igt.h"
+#include <errno.h>
+#include <getopt.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <strings.h>
+#include <unistd.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <assert.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include "intel_dp_compliance.h"
+
+#include <stdlib.h>
+#include <signal.h>
+
+/* User Input definitions */
+#define HELP_DESCRIPTION 1
+
+/* Debugfs file definitions */
+#define INTEL_DP_TEST_TYPE_FILE                "i915_dp_test_type"
+#define INTEL_DP_TEST_ACTIVE_FILE      "i915_dp_test_active"
+#define INTEL_DP_TEST_DATA_FILE                "i915_dp_test_data"
+
+/* DRM definitions - must be kept in sync with the DRM header */
+#define DP_TEST_LINK_TRAINING          (1 << 0)
+#define DP_TEST_LINK_VIDEO_PATTERN     (1 << 1)
+#define DP_TEST_LINK_EDID_READ         (1 << 2)
+#define DP_TEST_LINK_PHY_TEST_PATTERN  (1 << 3) /* DPCD >= 1.1 */
+
+#define DP_COMPLIANCE_TEST_TYPE_MASK   (DP_TEST_LINK_TRAINING      |   \
+                                        DP_TEST_LINK_VIDEO_PATTERN |   \
+                                        DP_TEST_LINK_EDID_READ     |   \
+                                        DP_TEST_LINK_PHY_TEST_PATTERN)
+
+/* NOTE: These must be kept in sync with the definitions in intel_dp.c */
+#define INTEL_DP_EDID_SHIFT_MASK       0
+#define INTEL_DP_EDID_OK               (0 << INTEL_DP_EDID_SHIFT_MASK)
+#define INTEL_DP_EDID_CORRUPT          (1 << INTEL_DP_EDID_SHIFT_MASK)
+#define INTEL_DP_RESOLUTION_SHIFT_MASK 0
+#define INTEL_DP_RESOLUTION_PREFERRED  (1 << INTEL_DP_RESOLUTION_SHIFT_MASK)
+#define INTEL_DP_RESOLUTION_STANDARD   (2 << INTEL_DP_RESOLUTION_SHIFT_MASK)
+#define INTEL_DP_RESOLUTION_FAILSAFE   (3 << INTEL_DP_RESOLUTION_SHIFT_MASK)
+#define DP_COMPLIANCE_VIDEO_MODE_MASK  (INTEL_DP_RESOLUTION_PREFERRED  |\
+                                        INTEL_DP_RESOLUTION_STANDARD   |\
+                                        INTEL_DP_RESOLUTION_FAILSAFE)
+
+/* Global file pointers for the sysfs files */
+FILE *test_active_fp, *test_data_fp, *test_type_fp;
+
+bool video_pattern_flag;
+
+/* Video pattern test globals */
+uint16_t hdisplay;
+uint16_t vdisplay;
+uint8_t bitdepth;
+
+static int tio_fd;
+struct termios saved_tio;
+
+drmModeRes *resources;
+int drm_fd, modes;
+uint64_t tiling = LOCAL_DRM_FORMAT_MOD_NONE;
+uint32_t depth = 24, stride, bpp;
+int specified_mode_num = -1, specified_disp_id = -1;
+int width, height;
+uint32_t test_crtc;
+uint32_t test_connector_id;
+enum {
+       INTEL_MODE_INVALID = -1,
+       INTEL_MODE_NONE = 0,
+       INTEL_MODE_PREFERRED,
+       INTEL_MODE_STANDARD,
+       INTEL_MODE_FAILSAFE,
+       INTEL_MODE_VIDEO_PATTERN_TEST
+} intel_display_mode;
+
+struct test_video_pattern {
+       uint16_t hdisplay;
+       uint16_t vdisplay;
+       uint8_t bitdepth;
+       uint32_t fb;
+       uint32_t size;
+       struct igt_fb fb_pattern;
+       drmModeModeInfo mode;
+       uint32_t *pixmap;
+};
+
+struct connector {
+       uint32_t id;
+       int mode_valid;
+       drmModeModeInfo mode, mode_standard, mode_preferred, mode_failsafe;
+       drmModeConnector *connector;
+       int crtc;
+       /* Standard and preferred frame buffer*/
+       uint32_t fb, fb_width, fb_height, fb_size;
+       uint8_t *pixmap;
+       struct igt_fb fb_video_pattern;
+       /* Failsafe framebuffer - note this is a 16-bit buffer */
+       uint32_t failsafe_fb, failsafe_width, failsafe_height;
+       uint32_t failsafe_size;
+       uint8_t *failsafe_pixmap;
+       struct igt_fb fb_failsafe_pattern;
+       struct test_video_pattern test_pattern;
+};
+
+static void clear_test_active(void)
+{
+       rewind(test_active_fp);
+       fprintf(test_active_fp, "%d", 0);
+       fflush(test_active_fp);
+}
+
+static void setup_debugfs_files(void)
+{
+       test_type_fp = igt_debugfs_fopen(INTEL_DP_TEST_TYPE_FILE, "r");
+       igt_require(test_type_fp);
+
+       test_data_fp = igt_debugfs_fopen(INTEL_DP_TEST_DATA_FILE, "r");
+       igt_require(test_data_fp);
+
+       test_active_fp = igt_debugfs_fopen(INTEL_DP_TEST_ACTIVE_FILE, "w+");
+       igt_require(test_active_fp);
+
+       /* Reset the active flag for safety */
+       clear_test_active();
+}
+
+static unsigned long get_test_type(void)
+{
+       unsigned long test_type;
+       int ret;
+
+       if (!test_type_fp)
+               fprintf(stderr, "Invalid test_type file\r\n");
+       rewind(test_type_fp);
+       ret = fscanf(test_type_fp, "%02lx", &test_type);
+       if (ret < 1 || test_type <= 0) {
+               igt_warn("test_type read failed - %02lx\r\n", test_type);
+               return 0;
+       }
+
+       return test_type;
+}
+
+static unsigned long get_test_edid_data(void)
+{
+       unsigned long test_data;
+       int ret;
+
+       if (!test_data_fp)
+               fprintf(stderr, "Invalid test_data file\r\n");
+
+       rewind(test_data_fp);
+       ret = fscanf(test_data_fp, "%lx", &test_data);
+       if (ret < 1 || test_data <= 0) {
+               igt_warn("test_data read failed - %lx\r\n", test_data);
+               return 0;
+       }
+
+       return test_data;
+}
+
+static void get_test_videopattern_data(void)
+{
+       int count = 0;
+       uint16_t video_pattern_value[3];
+       char video_pattern_attribute[15];
+       int ret;
+
+       if (!test_data_fp)
+               fprintf(stderr, "Invalid test_data file\r\n");
+
+       rewind(test_data_fp);
+       while (!feof(test_data_fp) && count < 3) {
+               ret = fscanf(test_data_fp, "%s %u\n", video_pattern_attribute,
+                      (unsigned int *)&video_pattern_value[count++]);
+               if (ret < 2) {
+                       igt_warn("test_data read failed\n");
+                       return;
+               }
+       }
+
+       hdisplay = video_pattern_value[0];
+       vdisplay = video_pattern_value[1];
+       bitdepth = video_pattern_value[2];
+       igt_info("Hdisplay = %d\r\n", hdisplay);
+       igt_info("Vdisplay = %d\r\n", vdisplay);
+       igt_info("BitDepth = %u\r\n", bitdepth);
+
+}
+
+static int process_test_request(int test_type)
+{
+       int mode;
+       unsigned long test_data_edid;
+       bool valid = false;
+       switch (test_type) {
+       case DP_TEST_LINK_VIDEO_PATTERN:
+               video_pattern_flag = true;
+               get_test_videopattern_data();
+               mode = INTEL_MODE_VIDEO_PATTERN_TEST;
+               valid = true;
+               break;
+       case DP_TEST_LINK_EDID_READ:
+               test_data_edid = get_test_edid_data();
+               mode = (test_data_edid & DP_COMPLIANCE_VIDEO_MODE_MASK) >>
+                       INTEL_DP_RESOLUTION_SHIFT_MASK;
+               valid = true;
+               break;
+       default:
+               /* Unknown test type */
+               fprintf(stderr, "Invalid test request, ignored.\r\n");
+               break;
+       }
+
+       if (valid)
+               return update_display(mode, true);
+
+       return -1;
+}
+
+static void dump_connectors_fd(int drmfd)
+{
+       int i, j;
+
+       drmModeRes *mode_resources = drmModeGetResources(drmfd);
+
+       if (!mode_resources) {
+               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
+               return;
+       }
+
+       igt_info("Connectors:\n");
+       igt_info("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\n");
+       for (i = 0; i < mode_resources->count_connectors; i++) {
+               drmModeConnector *connector;
+
+               connector = drmModeGetConnectorCurrent(drmfd,
+                                                      mode_resources->connectors[i]);
+               if (!connector) {
+                       igt_warn("Could not get connector %i: %s\n",
+                                mode_resources->connectors[i], strerror(errno));
+                       continue;
+               }
+
+               igt_info("%d\t%d\t%s\t%s\t%dx%d\t\t%d\n",
+                        connector->connector_id,
+                        connector->encoder_id,
+                        kmstest_connector_status_str(connector->connection),
+                        kmstest_connector_type_str(connector->connector_type),
+                        connector->mmWidth,
+                        connector->mmHeight,
+                        connector->count_modes);
+
+               if (!connector->count_modes)
+                       continue;
+
+               igt_info("  Modes:\n");
+               igt_info("  name refresh (Hz) hdisp hss hse htot vdisp ""vss vse vtot flags type clock\n");
+               for (j = 0; j < connector->count_modes; j++) {
+                       igt_info("[%d]", j);
+                       kmstest_dump_mode(&connector->modes[j]);
+               }
+
+               drmModeFreeConnector(connector);
+       }
+       igt_info("\n");
+
+       drmModeFreeResources(mode_resources);
+}
+
+static void dump_crtcs_fd(int drmfd)
+{
+       int i;
+       drmModeRes *mode_resources;
+
+       mode_resources = drmModeGetResources(drmfd);
+       if (!mode_resources) {
+               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
+               return;
+       }
+
+       igt_info("CRTCs:\n");
+       igt_info("id\tfb\tpos\tsize\n");
+       for (i = 0; i < mode_resources->count_crtcs; i++) {
+               drmModeCrtc *crtc;
+
+               crtc = drmModeGetCrtc(drmfd, mode_resources->crtcs[i]);
+               if (!crtc) {
+                       igt_warn("Could not get crtc %i: %s\n", mode_resources->crtcs[i], strerror(errno));
+                       continue;
+               }
+               igt_info("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+                        crtc->crtc_id,
+                        crtc->buffer_id,
+                        crtc->x,
+                        crtc->y,
+                        crtc->width,
+                        crtc->height);
+
+               kmstest_dump_mode(&crtc->mode);
+
+               drmModeFreeCrtc(crtc);
+       }
+       igt_info("\n");
+
+       drmModeFreeResources(mode_resources);
+}
+
+static void dump_info(void)
+{
+       dump_connectors_fd(drm_fd);
+       dump_crtcs_fd(drm_fd);
+}
+
+static int setup_framebuffers(struct connector *dp_conn)
+{
+
+       dp_conn->fb = igt_create_fb(drm_fd,
+                                   dp_conn->fb_width, dp_conn->fb_height,
+                                   DRM_FORMAT_XRGB8888,
+                                   LOCAL_DRM_FORMAT_MOD_NONE,
+                                   &dp_conn->fb_video_pattern);
+       igt_assert(dp_conn->fb);
+
+       /* Map the mapping of GEM object into the virtual address space */
+       dp_conn->pixmap = gem_mmap__gtt(drm_fd,
+                                       dp_conn->fb_video_pattern.gem_handle,
+                                       dp_conn->fb_video_pattern.size,
+                                       PROT_READ | PROT_WRITE);
+       if (dp_conn->pixmap == NULL)
+               return -1;
+
+       gem_set_domain(drm_fd, dp_conn->fb_video_pattern.gem_handle,
+                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+       dp_conn->fb_size = dp_conn->fb_video_pattern.size;
+
+       /* After filling the device memory with 0s it needs to be unmapped */
+       memset(dp_conn->pixmap, 0, dp_conn->fb_size);
+       munmap(dp_conn->pixmap, dp_conn->fb_size);
+
+       return 0;
+}
+
+static int setup_failsafe_framebuffer(struct connector *dp_conn)
+{
+
+       dp_conn->failsafe_fb = igt_create_fb(drm_fd,
+                                            dp_conn->failsafe_width,
+                                            dp_conn->failsafe_height,
+                                            DRM_FORMAT_XRGB8888,
+                                            LOCAL_DRM_FORMAT_MOD_NONE,
+                                            &dp_conn->fb_failsafe_pattern);
+       igt_assert(dp_conn->failsafe_fb);
+
+       /* Map the mapping of GEM object into the virtual address space */
+       dp_conn->failsafe_pixmap = gem_mmap__gtt(drm_fd,
+                                                dp_conn->fb_failsafe_pattern.gem_handle,
+                                                dp_conn->fb_failsafe_pattern.size,
+                                                PROT_READ | PROT_WRITE);
+       if (dp_conn->failsafe_pixmap == NULL)
+               return -1;
+
+       gem_set_domain(drm_fd, dp_conn->fb_failsafe_pattern.gem_handle,
+                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+       dp_conn->failsafe_size = dp_conn->fb_failsafe_pattern.size;
+
+       /* After filling the device framebuffer the mapped memory needs to be freed */
+       memset(dp_conn->failsafe_pixmap, 0, dp_conn->failsafe_size);
+       munmap(dp_conn->failsafe_pixmap, dp_conn->failsafe_size);
+
+       return 0;
+
+}
+
+static int setup_video_pattern_framebuffer(struct connector *dp_conn)
+{
+       uint32_t  video_width, video_height;
+
+       video_width = dp_conn->test_pattern.hdisplay;
+       video_height = dp_conn->test_pattern.vdisplay;
+       dp_conn->test_pattern.fb = igt_create_fb(drm_fd,
+                                                video_width, video_height,
+                                                DRM_FORMAT_XRGB8888,
+                                                LOCAL_DRM_FORMAT_MOD_NONE,
+                                                &dp_conn->test_pattern.fb_pattern);
+       igt_assert(dp_conn->test_pattern.fb);
+
+       /* Map the mapping of GEM object into the virtual address space */
+       dp_conn->test_pattern.pixmap = gem_mmap__gtt(drm_fd,
+                                                    dp_conn->test_pattern.fb_pattern.gem_handle,
+                                                    dp_conn->test_pattern.fb_pattern.size,
+                                                    PROT_READ | PROT_WRITE);
+       if (dp_conn->test_pattern.pixmap == NULL)
+               return -1;
+
+       gem_set_domain(drm_fd, dp_conn->test_pattern.fb_pattern.gem_handle,
+                      I915_GEM_DOMAIN_GTT, I915_GEM_DOMAIN_GTT);
+
+       dp_conn->test_pattern.size = dp_conn->test_pattern.fb_pattern.size;
+
+       memset(dp_conn->test_pattern.pixmap, 0, dp_conn->test_pattern.size);
+       return 0;
+
+}
+
+static int fill_framebuffer(struct connector *dp_conn)
+{
+       uint32_t tile_height, tile_width, video_width, video_height;
+       uint32_t *red_ptr, *green_ptr, *blue_ptr, *white_ptr, *src_ptr, *dst_ptr;
+       int x, y;
+       int32_t pixel_val;
+
+       video_width = dp_conn->test_pattern.hdisplay;
+       video_height = dp_conn->test_pattern.vdisplay;
+
+       tile_height = 64;
+       tile_width = 1 <<  (dp_conn->test_pattern.bitdepth);
+
+       red_ptr = dp_conn->test_pattern.pixmap;
+       green_ptr = red_ptr + (video_width * tile_height);
+       blue_ptr = green_ptr + (video_width * tile_height);
+       white_ptr = blue_ptr + (video_width * tile_height);
+       x = 0;
+
+       /* Fill the frame buffer with video pattern from CTS 3.1.5 */
+       while (x < video_width) {
+               for (pixel_val = 0; pixel_val < 256;
+                    pixel_val = pixel_val + (256 / tile_width)) {
+                       red_ptr[x] = pixel_val << 16;
+                       green_ptr[x] = pixel_val << 8;
+                       blue_ptr[x] = pixel_val << 0;
+                       white_ptr[x] = red_ptr[x] | green_ptr[x] | blue_ptr[x];
+                       if (++x >= video_width)
+                               break;
+               }
+       }
+       for (y = 0; y < video_height; y++) {
+               if (y == 0 || y == 64 || y == 128 || y == 192)
+                       continue;
+               switch ((y / tile_height) % 4) {
+               case 0:
+                       src_ptr = red_ptr;
+                       break;
+               case 1:
+                       src_ptr = green_ptr;
+                       break;
+               case 2:
+                       src_ptr = blue_ptr;
+                       break;
+               case 3:
+                       src_ptr = white_ptr;
+                       break;
+               }
+               dst_ptr = dp_conn->test_pattern.pixmap + (y * video_width);
+               memcpy(dst_ptr, src_ptr, (video_width * 4));
+       }
+       munmap(dp_conn->test_pattern.pixmap,
+              dp_conn->test_pattern.size);
+       return 0;
+}
+
+static int set_test_mode(struct connector *dp_conn)
+{
+       int ret = 0;
+       int i;
+       bool found_std = false, found_fs = false;
+       drmModeConnector *c = dp_conn->connector;
+
+       /* Ignore any disconnected devices */
+       if (c->connection != DRM_MODE_CONNECTED) {
+               igt_warn("Connector %u disconnected\r\n", c->connector_id);
+               return -ENOENT;
+       }
+       igt_info("Connector setup:\r\n");
+       /* Setup preferred mode - should be mode[0] in the list */
+       dp_conn->mode_preferred = c->modes[0];
+       dp_conn->fb_width = c->modes[0].hdisplay;
+       dp_conn->fb_height = c->modes[0].vdisplay;
+
+       dp_conn->test_pattern.mode = c->modes[0];
+       dp_conn->test_pattern.mode.hdisplay = c->modes[0].hdisplay;
+       dp_conn->test_pattern.mode.vdisplay = c->modes[0].vdisplay;
+
+       igt_info("Preferred mode (mode 0) for connector %u is %ux%u\r\n",
+                dp_conn->id, c->modes[0].hdisplay, c->modes[0].vdisplay);
+       fflush(stdin);
+
+       for (i = 1; i < c->count_modes; i++) {
+               /* Standard mode is 800x600@60 */
+               if (c->modes[i].hdisplay == 800 &&
+                   c->modes[i].vdisplay == 600 &&
+                   c->modes[i].vrefresh == 60 &&
+                   found_std == false) {
+                       dp_conn->mode_standard = c->modes[i];
+                       igt_info("Standard mode (%d) for connector %u is %ux%u\r\n",
+                                i,
+                                c->connector_id,
+                                c->modes[i].hdisplay,
+                                c->modes[i].vdisplay);
+                       found_std = true;
+               }
+               /* Failsafe mode is 640x480@60 */
+               if (c->modes[i].hdisplay == 640 &&
+                   c->modes[i].vdisplay == 480 &&
+                   c->modes[i].vrefresh == 60 &&
+                   found_fs == false) {
+                       dp_conn->mode_failsafe = c->modes[i];
+                       dp_conn->failsafe_width = c->modes[i].hdisplay;
+                       dp_conn->failsafe_height = c->modes[i].vdisplay;
+                       igt_info("Failsafe mode (%d) for connector %u is %ux%u\r\n",
+                                i,
+                                c->connector_id,
+                                c->modes[i].hdisplay,
+                                c->modes[i].vdisplay);
+                       found_fs = true;
+               }
+       }
+
+       ret = setup_framebuffers(dp_conn);
+       if (ret) {
+               igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
+                        c->connector_id, ret);
+               return ret;
+       }
+
+       if (found_fs) {
+               ret = setup_failsafe_framebuffer(dp_conn);
+               if (ret) {
+                       igt_warn("Creating failsafe framebuffer for connector %u failed (%d)\r\n",
+                                c->connector_id, ret);
+                       return ret;
+               }
+       }
+
+       if (video_pattern_flag) {
+               dp_conn->test_pattern.hdisplay = hdisplay;
+               dp_conn->test_pattern.vdisplay = vdisplay;
+               dp_conn->test_pattern.bitdepth = bitdepth;
+
+               ret = setup_video_pattern_framebuffer(dp_conn);
+               if (ret) {
+                       igt_warn("Creating framebuffer for connector %u failed (%d)\r\n",
+                                c->connector_id, ret);
+                       return ret;
+               }
+
+               ret = fill_framebuffer(dp_conn);
+               if (ret) {
+                       igt_warn("Filling framebuffer for connector %u failed (%d)\r\n",
+                                c->connector_id, ret);
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int set_video(int mode, struct connector *test_connector)
+{
+       drmModeModeInfo *requested_mode;
+       uint32_t required_fb_id;
+       struct igt_fb required_fb;
+       int ret = 0;
+
+       switch (mode) {
+       case INTEL_MODE_NONE:
+               igt_info("NONE\r\n");
+               ret = drmModeSetCrtc(drm_fd, test_connector->crtc,
+                                    -1, 0, 0, NULL, 0, NULL);
+               goto out;
+       case INTEL_MODE_PREFERRED:
+               igt_info("PREFERRED\r\n");
+               requested_mode =  &test_connector->mode_preferred;
+               required_fb_id = test_connector->fb;
+               required_fb = test_connector->fb_video_pattern;
+               break;
+       case INTEL_MODE_STANDARD:
+               igt_info("STANDARD\r\n");
+               requested_mode =  &test_connector->mode_standard;
+               required_fb_id = test_connector->fb;
+               required_fb = test_connector->fb_video_pattern;
+               break;
+       case INTEL_MODE_FAILSAFE:
+               igt_info("FAILSAFE\r\n");
+               requested_mode =  &test_connector->mode_failsafe;
+               required_fb_id = test_connector->failsafe_fb;
+               required_fb = test_connector->fb_failsafe_pattern;
+               break;
+       case INTEL_MODE_VIDEO_PATTERN_TEST:
+               igt_info("VIDEO PATTERN TEST\r\n");
+               requested_mode = &test_connector->test_pattern.mode;
+               required_fb_id = test_connector->test_pattern.fb;
+               required_fb = test_connector->test_pattern.fb_pattern;
+               break;
+       case INTEL_MODE_INVALID:
+       default:
+               igt_warn("INVALID! (%08x) Mode set aborted!\r\n", mode);
+               return -1;
+       }
+
+       igt_info("CRTC(%u):", test_connector->crtc);
+       kmstest_dump_mode(requested_mode);
+       ret = drmModeSetCrtc(drm_fd, test_connector->crtc, required_fb_id, 0, 0,
+                            &test_connector->id, 1, requested_mode);
+       if (ret) {
+               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
+                        requested_mode->hdisplay, requested_mode->vdisplay,
+                        requested_mode->vrefresh, strerror(errno));
+               igt_remove_fb(drm_fd, &required_fb);
+
+       }
+       /* Keep the pattern on output lines for 1 sec for DPR-120 to detect it */
+       sleep(1);
+
+out:
+       if (ret) {
+               igt_warn("Failed to set CRTC for connector %u\r\n",
+                        test_connector->id);
+       }
+
+       return ret;
+}
+
+static int
+set_default_mode(struct connector *c, bool set_mode)
+{
+       unsigned int fb_id = 0;
+       struct igt_fb fb_info;
+       int ret = 0;
+
+       if (!set_mode) {
+               ret = drmModeSetCrtc(drm_fd, c->crtc, 0, 0, 0,
+                                    NULL, 0, NULL);
+               if (ret)
+                       igt_warn("Failed to unset mode");
+               return ret;
+       }
+
+       c->mode = c->connector->modes[0];
+
+       width = c->mode.hdisplay;
+       height = c->mode.vdisplay;
+
+       fb_id = igt_create_pattern_fb(drm_fd, width, height,
+                                     DRM_FORMAT_XRGB8888,
+                                     tiling, &fb_info);
+
+       igt_info("CRTC(%u):[%d]", c->crtc, 0);
+       kmstest_dump_mode(&c->mode);
+       drmModeSetCrtc(drm_fd, c->crtc, -1, 0, 0, NULL, 0, NULL);
+       ret = drmModeSetCrtc(drm_fd, c->crtc, fb_id, 0, 0,
+                            &c->id, 1, &c->mode);
+       if (ret) {
+               igt_warn("Failed to set mode (%dx%d@%dHz): %s\n",
+                        width, height, c->mode.vrefresh, strerror(errno));
+               igt_remove_fb(drm_fd, &fb_info);
+
+       }
+
+       return ret;
+}
+
+static uint32_t find_crtc_for_connector(drmModeConnector *c)
+{
+       drmModeEncoder *e;
+       uint32_t possible_crtcs;
+       int i, j;
+
+       for (i = 0; i < c->count_encoders; i++) {
+               e = drmModeGetEncoder(drm_fd, c->encoders[i]);
+               possible_crtcs = e->possible_crtcs;
+               drmModeFreeEncoder(e);
+
+               for (j = 0; possible_crtcs >> j; j++)
+                       if (possible_crtcs & (1 << j))
+                               return resources->crtcs[j];
+       }
+       return 0;
+}
+
+/*
+ * Re-probe connectors and do a modeset based on test request or
+ * in case of a hotplug uevent.
+ *
+ * @mode: Video mode requested by the test
+ * @is_compliance_test: 1: If it is a compliance test
+ *                      0: If it is a hotplug event
+ *
+ * Returns:
+ * 0: On Success
+ * -1: On failure
+ */
+int update_display(int mode, bool is_compliance_test)
+{
+       struct connector *connectors, *conn;
+       int cnt, ret = 0;
+       bool set_mode;
+
+       resources = drmModeGetResources(drm_fd);
+       if (!resources) {
+               igt_warn("drmModeGetResources failed: %s\n", strerror(errno));
+               return -1;
+       }
+
+       connectors = calloc(resources->count_connectors,
+                           sizeof(struct connector));
+       if (!connectors)
+               return -1;
+
+       /* Find any connected displays */
+       for (cnt = 0; cnt < resources->count_connectors; cnt++) {
+               drmModeConnector *c;
+
+               conn = &connectors[cnt];
+               conn->id = resources->connectors[cnt];
+               c = drmModeGetConnector(drm_fd, conn->id);
+               if (c->connector_type == DRM_MODE_CONNECTOR_DisplayPort &&
+                   c->connection == DRM_MODE_CONNECTED) {
+                       test_connector_id = c->connector_id;
+                       conn->connector = c;
+                       conn->crtc = find_crtc_for_connector(c);
+                       test_crtc = conn->crtc;
+                       set_mode = true;
+                       break;
+               } else if (c->connector_id == test_connector_id &&
+                          c->connection == DRM_MODE_DISCONNECTED) {
+                       conn->connector = c;
+                       conn->crtc = test_crtc;
+                       set_mode = false;
+                       break;
+               }
+       }
+
+       if (cnt == resources->count_connectors) {
+               ret = -1;
+               goto err;
+       }
+
+       if (is_compliance_test) {
+               set_test_mode(conn);
+               ret = set_video(INTEL_MODE_NONE, conn);
+               ret = set_video(mode, conn);
+
+       } else
+               ret = set_default_mode(conn, set_mode);
+
+ err:
+       drmModeFreeConnector(conn->connector);
+       /* Error condition if no connected displays */
+       free(connectors);
+       drmModeFreeResources(resources);
+       return ret;
+}
+
+static const char optstr[] = "hi";
+
+static void __attribute__((noreturn)) usage(char *name, char opt)
+{
+       igt_info("usage: %s [-hi]\n", name);
+       igt_info("\t-i\tdump info\n");
+       igt_info("\tDefault is to respond to DPR-120 tests\n");
+       exit((opt != 'h') ? -1 : 0);
+}
+
+static void cleanup_debugfs(void)
+{
+       fclose(test_active_fp);
+       fclose(test_data_fp);
+       fclose(test_type_fp);
+}
+
+static void __attribute__((noreturn)) cleanup_and_exit(int ret)
+{
+       cleanup_debugfs();
+       close(drm_fd);
+       igt_info("Compliance testing application exiting\n");
+       exit(ret);
+}
+
+static void cleanup_test(void)
+{
+       video_pattern_flag = false;
+       hdisplay = 0;
+       vdisplay = 0;
+       bitdepth = 0;
+}
+
+static void read_test_request(void)
+{
+       unsigned long test_type;
+
+       test_type = get_test_type();
+       process_test_request(test_type);
+       cleanup_test();
+       clear_test_active();
+}
+
+static gboolean test_handler(GIOChannel *source, GIOCondition condition,
+                            gpointer data)
+{
+       unsigned long test_active;
+       int ret;
+
+       rewind(test_active_fp);
+
+       ret = fscanf(test_active_fp, "%lx", &test_active);
+       if (ret < 1)
+               return FALSE;
+
+       if (test_active)
+               read_test_request();
+       return TRUE;
+}
+
+static gboolean input_event(GIOChannel *source, GIOCondition condition,
+                               gpointer data)
+{
+       gchar buf[2];
+       gsize count;
+
+       count = read(g_io_channel_unix_get_fd(source), buf, sizeof(buf));
+       if (buf[0] == 'q' && (count == 1 || buf[1] == '\n')) {
+               cleanup_and_exit(0);
+       }
+
+       return TRUE;
+}
+
+static void enter_exec_path(char **argv)
+{
+       char *exec_path = NULL;
+       char *pos = NULL;
+       short len_path = 0;
+       int ret;
+
+       len_path = strlen(argv[0]);
+       exec_path = (char *) malloc(len_path);
+
+       memcpy(exec_path, argv[0], len_path);
+       pos = strrchr(exec_path, '/');
+       if (pos != NULL)
+               *(pos+1) = '\0';
+
+       ret = chdir(exec_path);
+       igt_assert_eq(ret, 0);
+       free(exec_path);
+}
+
+static void restore_termio_mode(int sig)
+{
+       tcsetattr(tio_fd, TCSANOW, &saved_tio);
+       close(tio_fd);
+}
+
+static void set_termio_mode(void)
+{
+       struct termios tio;
+
+       /* don't attempt to set terminal attributes if not in the foreground
+        * process group
+        */
+       if (getpgrp() != tcgetpgrp(STDOUT_FILENO))
+               return;
+
+       tio_fd = dup(STDIN_FILENO);
+       tcgetattr(tio_fd, &saved_tio);
+       igt_install_exit_handler(restore_termio_mode);
+       tio = saved_tio;
+       tio.c_lflag &= ~(ICANON | ECHO);
+       tcsetattr(tio_fd, TCSANOW, &tio);
+}
+
+int main(int argc, char **argv)
+{
+       int c;
+       int ret = 0;
+       GIOChannel *stdinchannel, *testactive_channel;
+       GMainLoop *mainloop;
+       bool opt_dump_info = false;
+       struct option long_opts[] = {
+               {"help-description", 0, 0, HELP_DESCRIPTION},
+               {"help", 0, 0, 'h'},
+       };
+
+       igt_skip_on_simulation();
+
+       enter_exec_path(argv);
+
+       while ((c = getopt_long(argc, argv, optstr, long_opts, NULL)) != -1) {
+               switch (c) {
+               case 'i':
+                       opt_dump_info = true;
+                       break;
+               case HELP_DESCRIPTION:
+                       igt_info("DP Compliance Test Suite using DPR-120\n");
+                       igt_info("EDID tests\n");
+                       igt_info("Video Pattern Generation tests\n");
+                       exit(0);
+                       break;
+               default:
+                       /* fall through */
+               case 'h':
+                       usage(argv[0], c);
+                       break;
+               }
+       }
+
+       set_termio_mode();
+
+       igt_info("*************DP Compliance Testing using DPR-120*************\n");
+       igt_info("Waiting for test request......\n");
+       drm_fd = drm_open_driver(DRIVER_ANY);
+
+       kmstest_set_vt_graphics_mode();
+       setup_debugfs_files();
+       cleanup_test();
+
+       if (opt_dump_info) {
+               dump_info();
+               goto out_close;
+       }
+
+       /* Get the DP connector ID and CRTC */
+       if (update_display(0, false)) {
+               igt_warn("Failed to set default mode\n");
+               ret = -1;
+               goto out_close;
+       }
+
+       mainloop = g_main_loop_new(NULL, FALSE);
+       if (!mainloop) {
+               igt_warn("Failed to create GMainLoop\n");
+               ret = -1;
+               goto out_close;
+       }
+
+       if (!intel_dp_compliance_setup_hotplug()) {
+               igt_warn("Failed to initialize hotplug support\n");
+               goto out_mainloop;
+       }
+
+       testactive_channel = g_io_channel_unix_new(fileno(test_active_fp));
+       if (!testactive_channel) {
+               igt_warn("Failed to create test_active GIOChannel\n");
+               goto out_close;
+       }
+
+       ret = g_io_add_watch(testactive_channel, G_IO_IN | G_IO_ERR,
+                            test_handler, NULL);
+       if (ret < 0) {
+               igt_warn("Failed to add watch on udev GIOChannel\n");
+               goto out_close;
+       }
+
+       stdinchannel = g_io_channel_unix_new(0);
+       if (!stdinchannel) {
+               igt_warn("Failed to create stdin GIOChannel\n");
+               goto out_hotplug;
+       }
+
+       ret = g_io_add_watch(stdinchannel, G_IO_IN | G_IO_ERR, input_event,
+                            NULL);
+       if (ret < 0) {
+               igt_warn("Failed to add watch on stdin GIOChannel\n");
+               goto out_stdio;
+       }
+
+       ret = 0;
+
+       g_main_loop_run(mainloop);
+
+out_stdio:
+       g_io_channel_shutdown(stdinchannel, TRUE, NULL);
+out_hotplug:
+       intel_dp_compliance_cleanup_hotplug();
+out_mainloop:
+       g_main_loop_unref(mainloop);
+out_close:
+       cleanup_debugfs();
+       close(drm_fd);
+
+       igt_assert_eq(ret, 0);
+
+       igt_info("Compliance testing application exiting\n");
+       igt_exit();
+}
diff --git a/tools/intel_dp_compliance.h b/tools/intel_dp_compliance.h
new file mode 100644
index 0000000..ade1e2f
--- /dev/null
+++ b/tools/intel_dp_compliance.h
@@ -0,0 +1,35 @@ 
+/*
+ * Copyright 2010 Intel Corporation
+ * Manasi Navare <manasi.d.navare@intel.com>
+ *
+ * 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 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+
+extern int drm_fd;
+
+gboolean intel_dp_compliance_setup_hotplug(void);
+void intel_dp_compliance_cleanup_hotplug(void);
+
+/* called by the hotplug code */
+int update_display(int mode, bool is_compliance_test);
diff --git a/tools/intel_dp_compliance_hotplug.c b/tools/intel_dp_compliance_hotplug.c
new file mode 100644
index 0000000..7c7ea65
--- /dev/null
+++ b/tools/intel_dp_compliance_hotplug.c
@@ -0,0 +1,123 @@ 
+/*
+ * Copyright 2010 Intel Corporation
+ *   Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * 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 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.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <sys/stat.h>
+
+#include "intel_dp_compliance.h"
+#include <libudev.h>
+static struct udev_monitor *uevent_monitor;
+static struct udev *udev;
+static GIOChannel *udevchannel;
+
+static gboolean hotplug_event(GIOChannel *source, GIOCondition condition,
+                             gpointer data)
+{
+       struct udev_device *dev;
+       dev_t udev_devnum;
+       struct stat s;
+       const char *hotplug;
+
+       dev = udev_monitor_receive_device(uevent_monitor);
+       if (!dev)
+               goto out;
+
+       udev_devnum = udev_device_get_devnum(dev);
+       fstat(drm_fd, &s);
+
+       hotplug = udev_device_get_property_value(dev, "HOTPLUG");
+
+       if (memcmp(&s.st_rdev, &udev_devnum, sizeof(dev_t)) == 0 &&
+           hotplug && atoi(hotplug) == 1)
+               update_display(0, false);
+
+       udev_device_unref(dev);
+out:
+       return TRUE;
+}
+
+
+gboolean intel_dp_compliance_setup_hotplug(void)
+{
+       int ret;
+
+       udev = udev_new();
+       if (!udev) {
+               igt_warn("Failed to create udev object\n");
+               goto out;
+       }
+
+       uevent_monitor = udev_monitor_new_from_netlink(udev, "udev");
+       if (!uevent_monitor) {
+               igt_warn("Failed to create udev event monitor\n");
+               goto out;
+       }
+
+       ret = udev_monitor_filter_add_match_subsystem_devtype(uevent_monitor,
+                                                             "drm",
+                                                             "drm_minor");
+       if (ret < 0) {
+               igt_warn("Failed to filter for drm events\n");
+               goto out;
+       }
+
+       ret = udev_monitor_enable_receiving(uevent_monitor);
+       if (ret < 0) {
+               igt_warn("Failed to enable udev event reception\n");
+               goto out;
+       }
+
+       udevchannel =
+               g_io_channel_unix_new(udev_monitor_get_fd(uevent_monitor));
+       if (!udevchannel) {
+               igt_warn("Failed to create udev GIOChannel\n");
+               goto out;
+       }
+
+       ret = g_io_add_watch(udevchannel, G_IO_IN | G_IO_ERR, hotplug_event,
+                            udev);
+       if (ret < 0) {
+               igt_warn("Failed to add watch on udev GIOChannel\n");
+               goto out;
+       }
+
+       return TRUE;
+
+out:
+       intel_dp_compliance_cleanup_hotplug();
+       return FALSE;
+}
+
+void intel_dp_compliance_cleanup_hotplug(void)
+{
+       if (udevchannel)
+               g_io_channel_shutdown(udevchannel, TRUE, NULL);
+       if (uevent_monitor)
+               udev_monitor_unref(uevent_monitor);
+       if (udev)
+               udev_unref(udev);
+}