Chris, happy with this revision?

On Fri, Oct 21, 2016 at 09:22:13AM +0530, Nautiyal Ankit wrote:
> From: Ramalingam C <[email protected]>
> 
> Idleness DRRS:
>       By default the DRRS state will be at DRRS_HIGH_RR. When a Display
>       content is Idle for more than 1Sec Idleness will be declared and
>       DRRS_LOW_RR will be invoked, changing the refresh rate to the
>       lower most refresh rate supported by the panel. As soon as there
>       is a display content change there will be a DRRS state transition
>       as DRRS_LOW_RR--> DRRS_HIGH_RR, changing the refresh rate to the
>       highest refresh rate supported by the panel.
> 
> To test this, Idleness DRRS IGT will probe the DRRS state at below
> instances and compare with the expected state.
> 
>       Instance                                        Expected State
> 1. Immediately after rendering the still image                DRRS_HIGH_RR
> 2. After a delay of 1.2Sec                            DRRS_LOW_RR
> 3. After changing the frame buffer                    DRRS_HIGH_RR
> 4. After a delay of 1.2Sec                            DRRS_LOW_RR
> 5. After changing the frame buffer                    DRRS_HIGH_RR
> 6. After a delay of 1.2Sec                            DRRS_LOW_RR
> 
> The test checks the driver DRRS state from the debugfs entry. To check the
> actual refresh-rate, a separate thread counts the number of vblanks
> received per sec. The refresh-rate calculated is checked against the
> expected refresh-rate with a tolerance value of 2.
> 
> This patch is a continuation of the earlier work
> https://patchwork.freedesktop.org/patch/45472/ towards igt for idleness
> 
> DRRS. The code is tested on Broxton BXT_T platform.
> 
> v2: Addressed the comments and suggestions from Vlad, Marius.
> The signoff details from the earlier work are also included.
> 
> v3: Modified vblank rate calculation by using reply-sequence, provided by
> drmWaitVBlank, as suggested by Chris Wilson.
> 
> Signed-off-by: Ramalingam C <[email protected]>
> Signed-off-by: Vandana Kannan <[email protected]>
> Signed-off-by: aknautiy <[email protected]>
> ---
>  tests/Makefile.sources |   1 +
>  tests/kms_drrs.c       | 599 
> +++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 600 insertions(+)
>  create mode 100644 tests/kms_drrs.c
> 
> diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> index a837977..5f31521 100644
> --- a/tests/Makefile.sources
> +++ b/tests/Makefile.sources
> @@ -91,6 +91,7 @@ TESTS_progs_M = \
>       kms_cursor_crc \
>       kms_cursor_legacy \
>       kms_draw_crc \
> +     kms_drrs \
>       kms_fbc_crc \
>       kms_fbcon_fbt \
>       kms_flip \
> diff --git a/tests/kms_drrs.c b/tests/kms_drrs.c
> new file mode 100644
> index 0000000..bd5a135
> --- /dev/null
> +++ b/tests/kms_drrs.c
> @@ -0,0 +1,599 @@
> +/*
> + * Copyright © 2016 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + */
> +
> +#include "drmtest.h"
> +#include "igt_debugfs.h"
> +#include "igt_kms.h"
> +#include "intel_chipset.h"
> +#include "intel_batchbuffer.h"
> +#include "ioctl_wrappers.h"
> +#include <time.h>
> +#include <pthread.h>
> +#include <stdlib.h>
> +#include <sys/time.h>
> +IGT_TEST_DESCRIPTION(
> +"Performs write operations and then waits for DRRS to invoke the"
> +"Low Refresh Rate and then disturbs the contents of the screen once"
> +"again hence DRRS revert back to High Refresh Rate(Default).");
> +
> +#define DRRS_STATUS_BYTES_CNT        1000
> +#define SET  1
> +#define RESET        0
> +
> +/*
> + * Structure to store data to create 2 framebuffers, fb[0] and fb[1] on a 
> given
> + * display. To disturb the content of the screen, we replace fb[0] by fb[1] 
> and
> + * vice versa.
> + */
> +typedef struct {
> +     int drm_fd;
> +     uint32_t devid;
> +     uint32_t handle[2];
> +     igt_display_t display;
> +     igt_output_t *output;
> +     enum pipe pipe;
> +     igt_plane_t *primary;
> +     struct igt_fb fb[2];
> +     uint32_t fb_id[2];
> +} data_t;
> +
> +/*
> + * Structure to count vblank and note the starting time of the counter
> + */
> +typedef struct {
> +     unsigned int vbl_count;
> +     struct timeval start;
> +} vbl_info;
> +
> +/*
> + * Condition variables,mutex, and shared variables for thread synchronization
> + */
> +pthread_mutex_t rr_mutex;
> +pthread_cond_t cv_rr_calc_requested;
> +pthread_cond_t cv_rr_calc_completed;
> +int rr_calc_requested = RESET;
> +int rr_calc_completed = RESET;
> +int thread_flag = SET;
> +int refresh_rate_shared = -1;
> +
> +/*
> + * Structure for refresh rate type
> + */
> +typedef struct{
> +     int rate;
> +     const char *name;
> +} refresh_rate_t;
> +
> +static inline uint32_t pipe_select(int pipe)
> +{
> +     if (pipe > 1)
> +             return pipe << DRM_VBLANK_HIGH_CRTC_SHIFT;
> +     else if (pipe > 0)
> +             return DRM_VBLANK_SECONDARY;
> +     else
> +             return 0;
> +}
> +
> +/*
> + * igt_millisec_elapsed:
> + *   Calculates the no. of millisec elapsed since timeval start
> + */
> +static double igt_millisec_elapsed(const struct timeval *start)
> +{
> +     struct timeval curr;
> +     double res;
> +
> +     gettimeofday(&curr, NULL);
> +     return (1e6*(curr.tv_sec - start->tv_sec) +
> +                             (curr.tv_usec - start->tv_usec)/1000.00);
> +}
> +
> +/*
> + * read_drrs_status :
> + *   Func to read the DRRS status from debugfs
> + */
> +static bool read_drrs_status(char *str)
> +{
> +     FILE *status;
> +     int cnt;
> +
> +     status = igt_debugfs_fopen("i915_drrs_status", "r");
> +     igt_assert(status);
> +
> +     cnt = fread(str, DRRS_STATUS_BYTES_CNT - 1, 1, status);
> +     if (!cnt) {
> +             if (!feof(status)) {
> +                     igt_info("ERROR: %d at fread\n", ferror(status));
> +                     return false;
> +             }
> +             clearerr(status);
> +     }
> +     fclose(status);
> +     return true;
> +}
> +
> +/*
> + * is_drrs_supported :
> + *   Func to check for DRRS support
> + */
> +static bool is_drrs_supported(void)
> +{
> +     char str[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     if (!read_drrs_status(str)) {
> +             igt_info("ERROR: Debugfs read FAILED\n");
> +             return false;
> +     }
> +     return strstr(str, "DRRS Supported: Yes") != NULL;
> +}
> +
> +/*
> + * is_drrs_enabled :
> + *   Func to check if DRRS is enabled by driver
> + */
> +static bool is_drrs_enabled(void)
> +{
> +     char str[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     if (!read_drrs_status(str)) {
> +             igt_info("ERROR: Debugfs read FAILED\n");
> +             return false;
> +     }
> +     return strstr(str, "Idleness DRRS: Disabled") == NULL;
> +}
> +
> +/*
> + * prepare_crtc :
> + *   Func to prepare crtc for the given display
> + */
> +static bool prepare_crtc(data_t *data)
> +{
> +     if (data == NULL)
> +             return false;
> +
> +     igt_display_t *display = &data->display;
> +     igt_output_t *output = data->output;
> +
> +     /* select the pipe we want to use */
> +     igt_output_set_pipe(output, data->pipe);
> +     igt_display_commit(display);
> +
> +     if (!output->valid) {
> +             igt_output_set_pipe(output, PIPE_ANY);
> +             igt_display_commit(display);
> +             return false;
> +     }
> +
> +     return true;
> +}
> +/*
> + * vbl_rate :
> + *   calculates the vblank rate by counting vblanks between start and end
> + *   period, divided by time between start and end.
> + */
> +static double vbl_rate(const union drm_wait_vblank *start,
> +                             const union drm_wait_vblank *end) {
> +     double s, e;
> +
> +     s = start->reply.tval_sec + 1e-6 * start->reply.tval_usec;
> +     e = end->reply.tval_sec + 1e-6 * end->reply.tval_usec;
> +     return ((end->reply.sequence - start->reply.sequence) / (e - s));
> +}
> +
> +/*
> + * calculate_refresh_rate :
> + *   Func to calculate the refresh rate by counting
> + *   vblanks in 1 sec (1000 ms). It returns the calculated refresh rate on
> + *   success. Returns -1 in case of error.
> + */
> +int calculate_refresh_rate(data_t *data)
> +{
> +#define PERIOD_MS 1000
> +     union drm_wait_vblank start, end;
> +     struct timeval start_tv;
> +
> +     memset(&start, 0, sizeof(start));
> +     start.request.type = DRM_VBLANK_RELATIVE | pipe_select(data->pipe);
> +     if (drmWaitVBlank(data->drm_fd, &start) != 0) {
> +             igt_info("ERROR : drmWaitVBlank Failed!\n");
> +             return -1;
> +     }
> +     gettimeofday(&start_tv, NULL);
> +     while (igt_millisec_elapsed(&start_tv) < PERIOD_MS) {
> +             memset(&end, 0, sizeof(end));
> +             end.request.type = DRM_VBLANK_RELATIVE |
> +                                             pipe_select(data->pipe);
> +             end.request.sequence = 1;
> +             if (drmWaitVBlank(data->drm_fd, &end) != 0) {
> +                     igt_info("ERROR : drmWaitVBlank Failed!\n");
> +                     return -1;
> +             }
> +     }
> +     return vbl_rate(&start, &end);
> +}
> +
> +/*
> + * worker_thread_func :
> + *   Func which is run by a worker thread to calculate the refresh_rate,
> + *   when signalled by the master thread.
> + */
> +void *worker_thread_func(void *ptr)
> +{
> +     data_t *data = (data_t *) ptr;
> +
> +     while (1) {
> +             int refresh_rate = 0;
> +             /*wait for signal from master*/
> +             pthread_mutex_lock(&rr_mutex);
> +             while (!rr_calc_requested)
> +                     pthread_cond_wait(&cv_rr_calc_requested, &rr_mutex);
> +
> +             /* checkpoint for thread termination */
> +             if (thread_flag == RESET) {
> +                     pthread_mutex_unlock(&rr_mutex);
> +                     pthread_exit(NULL);
> +             }
> +             rr_calc_requested = RESET;
> +             pthread_mutex_unlock(&rr_mutex);
> +             /*calculate refresh_rate*/
> +             refresh_rate = calculate_refresh_rate(data);
> +
> +             /* signal the master */
> +             pthread_mutex_lock(&rr_mutex);
> +             refresh_rate_shared = refresh_rate;
> +             rr_calc_completed = SET;
> +             pthread_mutex_unlock(&rr_mutex);
> +             pthread_cond_signal(&cv_rr_calc_completed);
> +     }
> +     return NULL;
> +}
> +
> +/*
> + * check_refresh_rate :
> + *   Func to check the refresh rate calculated, against the expected refresh
> + *   rate. It signals the worker thread to calculate the refresh-
> + *   rate, and checks if the correct refresh rate is switched.
> + *   Returns 0 in case of pass , 1 in case of failure, and -1 for error.
> + */
> +
> +static int check_refresh_rate(data_t *data, refresh_rate_t *expected_rr)
> +{
> +/*
> + * The calculated refresh-rate is an approximation to estimated refresh-rate.
> + * The tolerance threshold for the difference is set to 2. Difference more 
> than
> + * 2 is considered as failure for the check_refresh_rate.
> + */
> +#define TOLERANCE_THRESHOLD          2
> +     int refresh_rate = -1;
> +     char drrs_status[DRRS_STATUS_BYTES_CNT] = {};
> +
> +     /* Signal worker thread to calculate refresh rate */
> +     pthread_mutex_lock(&rr_mutex);
> +     rr_calc_requested = SET;
> +     pthread_mutex_unlock(&rr_mutex);
> +     pthread_cond_signal(&cv_rr_calc_requested);
> +
> +     /* Get the DRRS Status from the debugfs entry */
> +     if (!read_drrs_status(drrs_status)) {
> +             igt_info("ERROR : DRRS debugfs read FAILED\n");
> +             return -1;
> +     }
> +     /* Wait for the refresh rate calculator thread */
> +     pthread_mutex_lock(&rr_mutex);
> +     while (!rr_calc_completed)
> +             pthread_cond_wait(&cv_rr_calc_completed, &rr_mutex);
> +     rr_calc_completed = RESET;
> +     refresh_rate = refresh_rate_shared;
> +     pthread_mutex_unlock(&rr_mutex);
> +     if (refresh_rate < 0) {
> +             igt_info("ERROR : Refresh rate calculation FAILED\n");
> +             return -1;
> +     }
> +     igt_info("INFO : Actual Refresh_rate based on Vblank Counts/sec = %d\n"
> +                                                     , refresh_rate);
> +
> +     /* Compare with Expected Refresh Rate*/
> +     igt_info("INFO: Expected Refresh-Rate %d\n", expected_rr->rate);
> +     if (strstr(drrs_status, expected_rr->name) != NULL
> +     && abs(refresh_rate - expected_rr->rate) <= TOLERANCE_THRESHOLD) {
> +             igt_info("INFO: Expected %s : PASSED\n", expected_rr->name);
> +             return 0;
> +     }
> +
> +     igt_info("INFO : Expected %s : FAILED.\n", expected_rr->name);
> +     return 1;
> +}
> +
> +/*
> + * clean_up :
> + *   Func to stop the worker thread and destroy thread syncronization
> + *   structures.
> + */
> +void clean_up(pthread_t rr_thread)
> +{
> +     /* Stop the worker thread */
> +     pthread_mutex_lock(&rr_mutex);
> +     thread_flag = RESET;
> +     rr_calc_requested = SET;
> +     pthread_mutex_unlock(&rr_mutex);
> +     pthread_cond_signal(&cv_rr_calc_requested);
> +     pthread_join(rr_thread, NULL);
> +
> +     /* destroy the condition variables and mutex */
> +     pthread_cond_destroy(&cv_rr_calc_requested);
> +     pthread_cond_destroy(&cv_rr_calc_completed);
> +     pthread_mutex_destroy(&rr_mutex);
> +}
> +
> +/*
> + * execute_test:
> + *   This function
> + *   1. Initializes the thread sync structures.
> + *   2. Creates a worker thread which can be signaled to estimate
> + *   the refresh rates based on counting vblanks per sec.
> + *   3. Creates two different Framebuffer fb0, fb1
> + *   and apply them in the interval of 1.2Sec. So between FB change
> + *   DRRS should toggle from DRRS_HIGH_RR -> DRRS_LOW_RR.
> + *   And on next FB change DRRS_LOW_RR -> DRRS_HIGH_RR.
> + *
> + *   These expected transitions are verified using the kernel debugfs
> + *   and the refresh-rate, calculated by counting vblanks per sec by the
> + *   worker thread.
> + */
> +static int execute_test(data_t *data)
> +{
> +     igt_display_t *display = &data->display;
> +     igt_output_t *output = data->output;
> +     drmModeModeInfo *mode, *supported_modes;
> +     int test_failed = 0;
> +     int ret, i, count_modes;
> +     refresh_rate_t high_rr, low_rr;
> +     pthread_t rr_thread;
> +
> +     /*initialize the condition variables and  mutex*/
> +     pthread_cond_init(&cv_rr_calc_requested, NULL);
> +     pthread_cond_init(&cv_rr_calc_completed, NULL);
> +     pthread_mutex_init(&rr_mutex, NULL);
> +     thread_flag = SET;
> +     rr_calc_requested = RESET;
> +     rr_calc_completed = RESET;
> +     /* create a thread for calculating the refresh rate */
> +     ret = pthread_create(&rr_thread, NULL, worker_thread_func,
> +                                                     (void *) data);
> +     if (ret == -1) {
> +             igt_info("ERROR : Refresh rate thread creation FAILED\n");
> +             clean_up(rr_thread);
> +             return -1;
> +     }
> +
> +     high_rr.name = "DRRS_HIGH_RR";
> +     high_rr.rate = 0;
> +     low_rr.name = "DRRS_LOW_RR";
> +     low_rr.rate = 0;
> +     /* get the max and min supported refresh rates for the display */
> +     supported_modes = output->config.connector->modes;
> +     count_modes = output->config.connector->count_modes;
> +     /* minimum 2 modes are required for DRRS */
> +     if (count_modes < 2) {
> +             igt_info("ERROR: Minimum 2 modes required for DRRS\n");
> +             return -1;
> +     }
> +     for (i = 0; i < count_modes; i++) {
> +             int rr = supported_modes[i].vrefresh;
> +
> +             if (i == 0) {
> +                     high_rr.rate = low_rr.rate = rr;
> +                     continue;
> +             }
> +             if (high_rr.rate < rr)
> +                     high_rr.rate = rr;
> +             if (low_rr.rate > rr)
> +                     low_rr.rate = rr;
> +     }
> +     data->primary = igt_output_get_plane(data->output, IGT_PLANE_PRIMARY);
> +     mode = igt_output_get_mode(data->output);
> +     data->fb_id[0] = igt_create_color_fb(data->drm_fd, mode->hdisplay,
> +                     mode->vdisplay,
> +                     DRM_FORMAT_XRGB8888,
> +                     LOCAL_DRM_FORMAT_MOD_NONE,
> +                     0.0, 100.1, 0.0, &data->fb[0]);
> +     igt_assert(data->fb_id[0]);
> +     data->fb_id[1] = igt_create_color_fb(data->drm_fd, mode->hdisplay,
> +                     mode->vdisplay,
> +                     DRM_FORMAT_XRGB8888,
> +                     LOCAL_DRM_FORMAT_MOD_NONE,
> +                     100.1, 0.0, 0.0,
> +                     &data->fb[1]);
> +     igt_assert(data->fb_id[1]);
> +
> +     data->handle[0] = data->fb[0].gem_handle;
> +     data->handle[1] = data->fb[1].gem_handle;
> +
> +     /* scanout = fb[1] */
> +     igt_plane_set_fb(data->primary, &data->fb[1]);
> +     igt_display_commit(display);
> +     if (!is_drrs_enabled()) {
> +             igt_info("INFO : DRRS not enabled\n");
> +             igt_plane_set_fb(data->primary, NULL);
> +             igt_output_set_pipe(output, PIPE_ANY);
> +             igt_display_commit(display);
> +             igt_remove_fb(data->drm_fd, &data->fb[0]);
> +             igt_remove_fb(data->drm_fd, &data->fb[1]);
> +             clean_up(rr_thread);
> +             return -1;
> +     }
> +
> +     /* expecting High RR */
> +     ret =  check_refresh_rate(data, &high_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +     /* 1.2Sec to Enter the Idleness and check for Low Refresh Rate */
> +     usleep(1200000);
> +     ret =  check_refresh_rate(data, &low_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +
> +     /* scanout = fb[0] and check for High Refresh Rate*/
> +     igt_plane_set_fb(data->primary, &data->fb[0]);
> +     igt_display_commit(display);
> +     ret =  check_refresh_rate(data, &high_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +
> +     /* 1.2Sec to Enter the Idleness and check for Low Refresh Rate */
> +     usleep(1200000);
> +     ret =  check_refresh_rate(data, &low_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +
> +     /* scanout = fb[1] and check for High Refresh Rate*/
> +     igt_plane_set_fb(data->primary, &data->fb[1]);
> +     igt_display_commit(display);
> +     ret =  check_refresh_rate(data, &high_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +
> +     /* 1.2Sec to Enter the Idleness */
> +     usleep(1200000);
> +     ret =  check_refresh_rate(data, &low_rr);
> +     if (ret == -1)
> +             return -1;
> +     if (ret == 1)
> +             test_failed = 1;
> +
> +     clean_up(rr_thread);
> +     return test_failed;
> +}
> +
> +/*
> + * finish_crtc :
> + *   Func to free the framebuffers after the test completion.
> + */
> +static void finish_crtc(data_t *data)
> +{
> +     igt_plane_set_fb(data->primary, NULL);
> +     igt_output_set_pipe(data->output, PIPE_ANY);
> +     igt_display_commit(&data->display);
> +
> +     igt_remove_fb(data->drm_fd, &data->fb[0]);
> +     igt_remove_fb(data->drm_fd, &data->fb[1]);
> +}
> +
> +/*
> + * reset_display :
> + *   Func to reset the display structures after the test completion.
> + */
> +static void reset_display(data_t *data)
> +{
> +     igt_display_t *display = &data->display;
> +
> +     for_each_connected_output(display, data->output) {
> +             if (data->output->valid) {
> +                     data->primary =  igt_output_get_plane(data->output,
> +                                                     IGT_PLANE_PRIMARY);
> +                     igt_plane_set_fb(data->primary, NULL);
> +             }
> +             igt_output_set_pipe(data->output, PIPE_ANY);
> +     }
> +}
> +/*
> + * run_test :
> + *   Func to run the test for the eDP display.
> + */
> +static void run_test(data_t *data)
> +{
> +     igt_display_t *display = &data->display;
> +     int ret;
> +
> +     reset_display(data);
> +     /* Check for eDP Connector on PIPE A ,as eDP goes normally on PIPE_A */
> +     for_each_connected_output(display, data->output) {
> +             drmModeConnectorPtr c = data->output->config.connector;
> +
> +             if (c->connector_type != DRM_MODE_CONNECTOR_eDP ||
> +                     c->connection != DRM_MODE_CONNECTED)
> +                     continue;
> +             data->pipe = PIPE_A;
> +             igt_assert_f(prepare_crtc(data), "Failed to prepare CRTC\n");
> +             igt_info("INFO : Beginning %s on pipe %s,connector %s\n",
> +                                     igt_test_name(),
> +                                     kmstest_pipe_name(data->pipe),
> +                                     igt_output_name(data->output));
> +
> +             ret = execute_test(data);
> +             igt_skip_on_f(ret == -1,
> +                             "INFO :%s on pipe %s, connector %s:SKIPPED\n",
> +                                     igt_test_name(),
> +                                     kmstest_pipe_name(data->pipe),
> +                                     igt_output_name(data->output));
> +             igt_fail_on_f(ret == 1,
> +                             "INFO :%s on pipe %s, connector %s:FAILED\n",
> +                                     igt_test_name(),
> +                                     kmstest_pipe_name(data->pipe),
> +                                     igt_output_name(data->output));
> +
> +             igt_assert_f(ret == 0,
> +                             "INFO :%s on pipe %s, connector %s: PASSED\n",
> +                                     igt_test_name(),
> +                                     kmstest_pipe_name(data->pipe),
> +                                     igt_output_name(data->output));
> +
> +             finish_crtc(data);
> +     }
> +}
> +
> +igt_simple_main
> +{
> +     data_t data = {};
> +
> +     igt_skip_on_simulation();
> +     data.drm_fd = drm_open_driver_master(DRIVER_INTEL);
> +     if (data.drm_fd == -1) {
> +             igt_info("ERROR : invalid fd\n");
> +             return;
> +     }
> +     data.devid = intel_get_drm_devid(data.drm_fd);
> +     if (data.devid < 0) {
> +             igt_info("ERROR : invalid dev id\n");
> +             return;
> +     }
> +     /* Check if the DRRS is supported.
> +      * If yes call the Idleness DRRS test
> +      */
> +     igt_require_f(is_drrs_supported(),
> +                     "DRRS not supported:check VBT/panel caps\n");
> +     igt_display_init(&data.display, data.drm_fd);
> +     run_test(&data);
> +     igt_display_fini(&data.display);
> +}
> -- 
> 2.7.4
> 
> _______________________________________________
> Intel-gfx mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to